@instantdb/core 0.22.167 → 0.22.168

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.
@@ -52,6 +52,8 @@ const defaultConfig = {
52
52
  };
53
53
  // Param that the backend adds if this is an oauth redirect
54
54
  const OAUTH_REDIRECT_PARAM = '_instant_oauth_redirect';
55
+ const OAUTH_EXTRA_FIELDS_ID_PARAM = '_instant_extra_fields_id';
56
+ const oauthExtraFieldsKey = 'oauthExtraFields';
55
57
  const currentUserKey = `currentUser`;
56
58
  /**
57
59
  * @param {Object} config
@@ -1513,6 +1515,7 @@ export default class Reactor {
1513
1515
  if (url.searchParams.get(OAUTH_REDIRECT_PARAM)) {
1514
1516
  const startUrl = url.toString();
1515
1517
  url.searchParams.delete(OAUTH_REDIRECT_PARAM);
1518
+ url.searchParams.delete(OAUTH_EXTRA_FIELDS_ID_PARAM);
1516
1519
  url.searchParams.delete('code');
1517
1520
  url.searchParams.delete('error');
1518
1521
  const newPath = url.pathname +
@@ -1575,8 +1578,20 @@ export default class Reactor {
1575
1578
  if (!code) {
1576
1579
  return null;
1577
1580
  }
1581
+ const extraFieldsId = params.get(OAUTH_EXTRA_FIELDS_ID_PARAM);
1578
1582
  this._replaceUrlAfterOAuth();
1579
1583
  try {
1584
+ let extraFields;
1585
+ const stored = await this.kv.waitForKeyToLoad(oauthExtraFieldsKey);
1586
+ if (extraFieldsId && stored) {
1587
+ extraFields = stored[extraFieldsId];
1588
+ }
1589
+ // Clean up all stored extraFields after login
1590
+ if (stored) {
1591
+ this.kv.updateInPlace((prev) => {
1592
+ delete prev[oauthExtraFieldsKey];
1593
+ });
1594
+ }
1580
1595
  const currentUser = await this._getCurrentUser();
1581
1596
  const isGuest = currentUser?.type === 'guest';
1582
1597
  const { user } = await authAPI.exchangeCodeForToken({
@@ -1584,6 +1599,7 @@ export default class Reactor {
1584
1599
  appId: this.config.appId,
1585
1600
  code,
1586
1601
  refreshToken: isGuest ? currentUser.refresh_token : undefined,
1602
+ extraFields,
1587
1603
  });
1588
1604
  this.setCurrentUser(user);
1589
1605
  return null;
@@ -1801,15 +1817,16 @@ export default class Reactor {
1801
1817
  email: email,
1802
1818
  });
1803
1819
  }
1804
- async signInWithMagicCode({ email, code }) {
1820
+ async signInWithMagicCode(params) {
1805
1821
  const currentUser = await this.getCurrentUser();
1806
1822
  const isGuest = currentUser?.user?.type === 'guest';
1807
- const res = await authAPI.verifyMagicCode({
1823
+ const res = await authAPI.checkMagicCode({
1808
1824
  apiURI: this.config.apiURI,
1809
1825
  appId: this.config.appId,
1810
- email,
1811
- code,
1826
+ email: params.email,
1827
+ code: params.code,
1812
1828
  refreshToken: isGuest ? currentUser?.user?.refresh_token : undefined,
1829
+ extraFields: params.extraFields,
1813
1830
  });
1814
1831
  await this.changeCurrentUser(res.user);
1815
1832
  return res;
@@ -1863,18 +1880,35 @@ export default class Reactor {
1863
1880
  * @param {Object} params - The parameters to create the authorization URL.
1864
1881
  * @param {string} params.clientName - The name of the client requesting authorization.
1865
1882
  * @param {string} params.redirectURL - The URL to redirect users to after authorization.
1883
+ * @param {Record<string, any>} [params.extraFields] - Extra fields to write to $users on creation
1866
1884
  * @returns {string} The created authorization URL.
1867
1885
  */
1868
- createAuthorizationURL({ clientName, redirectURL }) {
1886
+ createAuthorizationURL({ clientName, redirectURL, extraFields }) {
1869
1887
  const { apiURI, appId } = this.config;
1870
- return `${apiURI}/runtime/oauth/start?app_id=${appId}&client_name=${clientName}&redirect_uri=${redirectURL}`;
1888
+ let finalRedirectURL = redirectURL;
1889
+ if (extraFields) {
1890
+ // Store extraFields under a unique ID so multiple
1891
+ // createAuthorizationURL calls don't overwrite each other.
1892
+ // The ID is passed through the redirect URL and used
1893
+ // by _oauthLoginInit to retrieve the right extraFields.
1894
+ // All entries are cleaned up after login.
1895
+ const extraFieldsId = `${Math.random().toString(36).slice(2)}`;
1896
+ this.kv.updateInPlace((prev) => {
1897
+ const stored = prev[oauthExtraFieldsKey] || {};
1898
+ stored[extraFieldsId] = extraFields;
1899
+ prev[oauthExtraFieldsKey] = stored;
1900
+ });
1901
+ finalRedirectURL = `${redirectURL}${redirectURL.includes('?') ? '&' : '?'}${OAUTH_EXTRA_FIELDS_ID_PARAM}=${extraFieldsId}`;
1902
+ }
1903
+ return `${apiURI}/runtime/oauth/start?app_id=${appId}&client_name=${clientName}&redirect_uri=${encodeURIComponent(finalRedirectURL)}`;
1871
1904
  }
1872
1905
  /**
1873
1906
  * @param {Object} params
1874
1907
  * @param {string} params.code - The code received from the OAuth service.
1875
1908
  * @param {string} [params.codeVerifier] - The code verifier used to generate the code challenge.
1909
+ * @param {Record<string, any>} [params.extraFields] - Extra fields to write to $users on creation
1876
1910
  */
1877
- async exchangeCodeForToken({ code, codeVerifier }) {
1911
+ async exchangeCodeForToken({ code, codeVerifier, extraFields }) {
1878
1912
  const currentUser = await this.getCurrentUser();
1879
1913
  const isGuest = currentUser?.user?.type === 'guest';
1880
1914
  const res = await authAPI.exchangeCodeForToken({
@@ -1883,6 +1917,7 @@ export default class Reactor {
1883
1917
  code: code,
1884
1918
  codeVerifier,
1885
1919
  refreshToken: isGuest ? currentUser?.user?.refresh_token : undefined,
1920
+ extraFields,
1886
1921
  });
1887
1922
  await this.changeCurrentUser(res.user);
1888
1923
  return res;
@@ -1896,17 +1931,19 @@ export default class Reactor {
1896
1931
  * @param {string} params.clientName - The name of the client requesting authorization.
1897
1932
  * @param {string} params.idToken - The id_token from the external service
1898
1933
  * @param {string | null | undefined} [params.nonce] - The nonce used when requesting the id_token from the external service
1934
+ * @param {Record<string, any>} [params.extraFields] - Extra fields to write to $users on creation
1899
1935
  */
1900
- async signInWithIdToken({ idToken, clientName, nonce }) {
1936
+ async signInWithIdToken(params) {
1901
1937
  const currentUser = await this.getCurrentUser();
1902
1938
  const refreshToken = currentUser?.user?.refresh_token;
1903
1939
  const res = await authAPI.signInWithIdToken({
1904
1940
  apiURI: this.config.apiURI,
1905
1941
  appId: this.config.appId,
1906
- idToken,
1907
- clientName,
1908
- nonce,
1942
+ idToken: params.idToken,
1943
+ clientName: params.clientName,
1944
+ nonce: params.nonce,
1909
1945
  refreshToken,
1946
+ extraFields: params.extraFields,
1910
1947
  });
1911
1948
  await this.changeCurrentUser(res.user);
1912
1949
  return res;