@nauth-toolkit/client 0.1.83 → 0.1.85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -568,6 +568,7 @@ var FetchAdapter = class {
568
568
  };
569
569
 
570
570
  // src/core/challenge-router.ts
571
+ var OAUTH_STATE_KEY = "nauth_oauth_state";
571
572
  var ChallengeRouter = class {
572
573
  constructor(config) {
573
574
  this.config = config;
@@ -586,7 +587,8 @@ var ChallengeRouter = class {
586
587
  if (response.challengeName) {
587
588
  await this.navigateToChallenge(response);
588
589
  } else {
589
- await this.navigateToSuccess();
590
+ const queryParams = await this.getStoredOauthState();
591
+ await this.navigateToSuccess(queryParams);
590
592
  }
591
593
  }
592
594
  /**
@@ -600,11 +602,44 @@ var ChallengeRouter = class {
600
602
  }
601
603
  /**
602
604
  * Navigate to success URL.
605
+ *
606
+ * @param queryParams - Optional query parameters to append to the success URL
607
+ *
608
+ * @example
609
+ * ```typescript
610
+ * await router.navigateToSuccess({ appState: 'invite-code-123' });
611
+ * ```
603
612
  */
604
- async navigateToSuccess() {
605
- const url = this.config.redirects?.success || "/";
613
+ async navigateToSuccess(queryParams) {
614
+ let url = this.config.redirects?.success || "/";
615
+ if (queryParams && Object.keys(queryParams).length > 0) {
616
+ const searchParams = new URLSearchParams();
617
+ Object.entries(queryParams).forEach(([key, value]) => {
618
+ if (value) {
619
+ searchParams.set(key, value);
620
+ }
621
+ });
622
+ const queryString = searchParams.toString();
623
+ url = queryString ? `${url}${url.includes("?") ? "&" : "?"}${queryString}` : url;
624
+ }
606
625
  await this.navigate(url);
607
626
  }
627
+ /**
628
+ * Retrieve stored OAuth appState from storage.
629
+ *
630
+ * @returns Query params object with appState if present, undefined otherwise
631
+ */
632
+ async getStoredOauthState() {
633
+ try {
634
+ const stored = await this.config.storage.getItem(OAUTH_STATE_KEY);
635
+ if (stored) {
636
+ await this.config.storage.removeItem(OAUTH_STATE_KEY);
637
+ return { appState: stored };
638
+ }
639
+ } catch {
640
+ }
641
+ return void 0;
642
+ }
608
643
  /**
609
644
  * Navigate to error URL.
610
645
  *
@@ -719,6 +754,7 @@ var ChallengeRouter = class {
719
754
  // src/core/client.ts
720
755
  var USER_KEY2 = "nauth_user";
721
756
  var CHALLENGE_KEY2 = "nauth_challenge_session";
757
+ var OAUTH_STATE_KEY2 = "nauth_oauth_state";
722
758
  var hasWindow = () => typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined";
723
759
  var defaultStorage = () => {
724
760
  if (hasWindow() && typeof window.localStorage !== "undefined") {
@@ -1502,13 +1538,19 @@ var NAuthClient = class {
1502
1538
  }
1503
1539
  /**
1504
1540
  * Build request headers for authentication.
1541
+ *
1542
+ * @param auth - Whether to include authentication headers
1543
+ * @param method - HTTP method (GET, POST, PUT, DELETE, PATCH)
1544
+ * @returns Headers object with auth, CSRF, and device trust headers
1505
1545
  * @private
1506
1546
  */
1507
- async buildHeaders(auth) {
1547
+ async buildHeaders(auth, method = "GET") {
1508
1548
  const headers = {
1509
- "Content-Type": "application/json",
1510
1549
  ...this.config.headers
1511
1550
  };
1551
+ if (method !== "GET") {
1552
+ headers["Content-Type"] = "application/json";
1553
+ }
1512
1554
  if (auth && this.config.tokenDelivery === "json") {
1513
1555
  const accessToken = (await this.tokenManager.getTokens()).accessToken;
1514
1556
  if (accessToken) {
@@ -1524,7 +1566,8 @@ var NAuthClient = class {
1524
1566
  } catch {
1525
1567
  }
1526
1568
  }
1527
- if (this.config.tokenDelivery === "cookies" && hasWindow()) {
1569
+ const mutatingMethods = ["POST", "PUT", "PATCH", "DELETE"];
1570
+ if (this.config.tokenDelivery === "cookies" && hasWindow() && mutatingMethods.includes(method)) {
1528
1571
  const csrfToken = this.getCsrfToken();
1529
1572
  if (csrfToken) {
1530
1573
  headers[this.config.csrf.headerName] = csrfToken;
@@ -1547,7 +1590,7 @@ var NAuthClient = class {
1547
1590
  */
1548
1591
  async get(path, auth = false) {
1549
1592
  const url = this.buildUrl(path);
1550
- const headers = await this.buildHeaders(auth);
1593
+ const headers = await this.buildHeaders(auth, "GET");
1551
1594
  const credentials = this.config.tokenDelivery === "cookies" ? "include" : "omit";
1552
1595
  const response = await this.config.httpAdapter.request({
1553
1596
  method: "GET",
@@ -1563,7 +1606,7 @@ var NAuthClient = class {
1563
1606
  */
1564
1607
  async post(path, body, auth = false) {
1565
1608
  const url = this.buildUrl(path);
1566
- const headers = await this.buildHeaders(auth);
1609
+ const headers = await this.buildHeaders(auth, "POST");
1567
1610
  const credentials = this.config.tokenDelivery === "cookies" ? "include" : "omit";
1568
1611
  const response = await this.config.httpAdapter.request({
1569
1612
  method: "POST",
@@ -1580,7 +1623,7 @@ var NAuthClient = class {
1580
1623
  */
1581
1624
  async put(path, body, auth = false) {
1582
1625
  const url = this.buildUrl(path);
1583
- const headers = await this.buildHeaders(auth);
1626
+ const headers = await this.buildHeaders(auth, "PUT");
1584
1627
  const credentials = this.config.tokenDelivery === "cookies" ? "include" : "omit";
1585
1628
  const response = await this.config.httpAdapter.request({
1586
1629
  method: "PUT",
@@ -1597,7 +1640,7 @@ var NAuthClient = class {
1597
1640
  */
1598
1641
  async delete(path, auth = false) {
1599
1642
  const url = this.buildUrl(path);
1600
- const headers = await this.buildHeaders(auth);
1643
+ const headers = await this.buildHeaders(auth, "DELETE");
1601
1644
  const credentials = this.config.tokenDelivery === "cookies" ? "include" : "omit";
1602
1645
  const response = await this.config.httpAdapter.request({
1603
1646
  method: "DELETE",
@@ -1622,6 +1665,53 @@ var NAuthClient = class {
1622
1665
  getChallengeRouter() {
1623
1666
  return this.challengeRouter;
1624
1667
  }
1668
+ /**
1669
+ * Store OAuth appState from social redirect callback.
1670
+ *
1671
+ * This is called automatically by the social redirect callback guard
1672
+ * when appState is present in the callback URL. The stored state can
1673
+ * be retrieved using getLastOauthState().
1674
+ *
1675
+ * @param appState - OAuth appState value from callback URL
1676
+ *
1677
+ * @example
1678
+ * ```typescript
1679
+ * await client.storeOauthState('invite-code-123');
1680
+ * ```
1681
+ */
1682
+ async storeOauthState(appState) {
1683
+ if (appState && appState.trim() !== "") {
1684
+ await this.config.storage.setItem(OAUTH_STATE_KEY2, appState);
1685
+ }
1686
+ }
1687
+ /**
1688
+ * Get the last OAuth appState from social redirect callback.
1689
+ *
1690
+ * Returns the appState that was stored during the most recent social
1691
+ * login redirect callback. This is useful for restoring UI state,
1692
+ * applying invite codes, or tracking referral information.
1693
+ *
1694
+ * The state is automatically cleared after retrieval to prevent reuse.
1695
+ *
1696
+ * @returns The stored appState, or null if none exists
1697
+ *
1698
+ * @example
1699
+ * ```typescript
1700
+ * const appState = await client.getLastOauthState();
1701
+ * if (appState) {
1702
+ * // Apply invite code or restore UI state
1703
+ * console.log('OAuth state:', appState);
1704
+ * }
1705
+ * ```
1706
+ */
1707
+ async getLastOauthState() {
1708
+ const stored = await this.config.storage.getItem(OAUTH_STATE_KEY2);
1709
+ if (stored) {
1710
+ await this.config.storage.removeItem(OAUTH_STATE_KEY2);
1711
+ return stored;
1712
+ }
1713
+ return null;
1714
+ }
1625
1715
  };
1626
1716
 
1627
1717
  // src/core/challenge-helpers.ts