@nurama/sdk 1.4.0 → 1.4.2

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.
Files changed (41) hide show
  1. package/dist/NuramaClient.d.ts +32 -0
  2. package/dist/NuramaClient.d.ts.map +1 -1
  3. package/dist/NuramaClient.js +38 -0
  4. package/dist/NuramaClient.js.map +1 -1
  5. package/dist/browser/nurama-bot-sdk.js +333 -28
  6. package/dist/browser/nurama-bot-sdk.min.js +1 -1
  7. package/dist/browser/nurama-sdk.js +333 -28
  8. package/dist/browser/nurama-sdk.min.js +1 -1
  9. package/dist/routes/bot.d.ts +60 -5
  10. package/dist/routes/bot.d.ts.map +1 -1
  11. package/dist/routes/bot.js +72 -0
  12. package/dist/routes/bot.js.map +1 -1
  13. package/dist/routes/device.d.ts +16 -1
  14. package/dist/routes/device.d.ts.map +1 -1
  15. package/dist/routes/device.js +34 -0
  16. package/dist/routes/device.js.map +1 -1
  17. package/dist/routes/joinLink.d.ts +51 -1
  18. package/dist/routes/joinLink.d.ts.map +1 -1
  19. package/dist/routes/joinLink.js +124 -0
  20. package/dist/routes/joinLink.js.map +1 -1
  21. package/dist/routes/oauthGrant.d.ts +45 -0
  22. package/dist/routes/oauthGrant.d.ts.map +1 -0
  23. package/dist/routes/oauthGrant.js +32 -0
  24. package/dist/routes/oauthGrant.js.map +1 -0
  25. package/dist/routes/socket.d.ts.map +1 -1
  26. package/dist/routes/socket.js +47 -29
  27. package/dist/routes/socket.js.map +1 -1
  28. package/dist/routes/token.d.ts +23 -1
  29. package/dist/routes/token.d.ts.map +1 -1
  30. package/dist/routes/token.js +22 -0
  31. package/dist/routes/token.js.map +1 -1
  32. package/dist/version.js +4 -4
  33. package/package.json +2 -2
  34. package/src/NuramaClient.ts +60 -0
  35. package/src/routes/bot.ts +104 -5
  36. package/src/routes/device.ts +38 -0
  37. package/src/routes/joinLink.ts +133 -0
  38. package/src/routes/oauthGrant.ts +64 -0
  39. package/src/routes/socket.ts +51 -33
  40. package/src/routes/token.ts +40 -1
  41. package/src/version.ts +4 -4
@@ -7880,6 +7880,118 @@
7880
7880
  sendJWT: true
7881
7881
  });
7882
7882
  },
7883
+ /** The queue of people waiting on a decision for this project. */
7884
+ async getJoinRequests(params) {
7885
+ if (!params?.projectId) throw new Error("projectId is required.");
7886
+ return client._request({
7887
+ method: "GET",
7888
+ endpoint: "/v1/join-links/requests",
7889
+ params,
7890
+ sendJWT: true
7891
+ });
7892
+ },
7893
+ /**
7894
+ * The caller's own requests still waiting on a decision.
7895
+ *
7896
+ * Needs no `projectId`: it is scoped server-side to the caller, who is not
7897
+ * a member of the projects they are waiting on and so cannot read those
7898
+ * projects' queues.
7899
+ */
7900
+ async getMyJoinRequests() {
7901
+ return client._request({
7902
+ method: "GET",
7903
+ endpoint: "/v1/join-links/requests/mine",
7904
+ sendJWT: true
7905
+ });
7906
+ },
7907
+ /**
7908
+ * Approve a request and admit the person.
7909
+ *
7910
+ * Seats and the link's remaining uses are re-checked here, not when the
7911
+ * request was made — a queue outlives the capacity that existed when it was
7912
+ * filled, so approval can legitimately fail on a seat limit.
7913
+ */
7914
+ async approveJoinRequest(requestId, projectId) {
7915
+ if (!requestId) throw new Error("requestId is required.");
7916
+ if (!projectId) throw new Error("projectId is required.");
7917
+ return client._request({
7918
+ method: "POST",
7919
+ endpoint: `/v1/join-links/requests/${requestId}/approve`,
7920
+ body: { projectId },
7921
+ sendJWT: true
7922
+ });
7923
+ },
7924
+ /**
7925
+ * Reject a request, optionally barring the person.
7926
+ *
7927
+ * Passing `ban` is destructive beyond the refusal: a ban REMOVES an existing
7928
+ * membership, so it can take away access the person already had in scope.
7929
+ * It is a separate field for that reason, never implied by the rejection.
7930
+ */
7931
+ async rejectJoinRequest(requestId, data) {
7932
+ if (!requestId) throw new Error("requestId is required.");
7933
+ if (!data?.projectId) throw new Error("projectId is required.");
7934
+ return client._request({
7935
+ method: "POST",
7936
+ endpoint: `/v1/join-links/requests/${requestId}/reject`,
7937
+ body: data,
7938
+ sendJWT: true
7939
+ });
7940
+ },
7941
+ /**
7942
+ * Change or lift the cooldown on a rejected request.
7943
+ *
7944
+ * Only a rejected request has one; `reapplyAfter: null` lifts it, letting
7945
+ * the person ask again straight away. A barred person is refused — the ban
7946
+ * already blocks every path, so lifting that is the action that matters.
7947
+ */
7948
+ async updateJoinRequestCooldown(requestId, data) {
7949
+ if (!requestId) throw new Error("requestId is required.");
7950
+ if (!data?.projectId) throw new Error("projectId is required.");
7951
+ return client._request({
7952
+ method: "PATCH",
7953
+ endpoint: `/v1/join-links/requests/${requestId}/cooldown`,
7954
+ body: { projectId: data.projectId, reapplyAfter: data.reapplyAfter ?? null },
7955
+ sendJWT: true
7956
+ });
7957
+ },
7958
+ /**
7959
+ * Bar someone, without a request to refuse.
7960
+ *
7961
+ * Destructive: the ban REMOVES every membership the person holds in its
7962
+ * scope, so a `workspace` ban clears them out of every project in it. An
7963
+ * owner cannot be barred, and neither can you bar yourself.
7964
+ */
7965
+ async createResourceBan(data) {
7966
+ if (!data?.projectId) throw new Error("projectId is required.");
7967
+ if (!data?.userId) throw new Error("userId is required.");
7968
+ if (!data?.scope) throw new Error("scope is required.");
7969
+ return client._request({
7970
+ method: "POST",
7971
+ endpoint: "/v1/join-links/bans",
7972
+ body: data,
7973
+ sendJWT: true
7974
+ });
7975
+ },
7976
+ /** People barred from this project, newest first. */
7977
+ async getResourceBans(params) {
7978
+ if (!params?.projectId) throw new Error("projectId is required.");
7979
+ return client._request({
7980
+ method: "GET",
7981
+ endpoint: "/v1/join-links/bans",
7982
+ params,
7983
+ sendJWT: true
7984
+ });
7985
+ },
7986
+ /** Lift a ban. It does not restore any membership the ban removed. */
7987
+ async liftResourceBan(banId) {
7988
+ if (!banId) throw new Error("banId is required.");
7989
+ return client._request({
7990
+ method: "DELETE",
7991
+ endpoint: `/v1/join-links/bans/${banId}`,
7992
+ sendJWT: true
7993
+ });
7994
+ },
7883
7995
  /** Update a join link's settings (role, mode, domains, expiry, enable/disable). */
7884
7996
  async updateJoinLink(linkId, data) {
7885
7997
  if (!linkId) throw new Error("linkId is required.");
@@ -8306,6 +8418,19 @@
8306
8418
  "reconnect_failed",
8307
8419
  "reconnect"
8308
8420
  ]);
8421
+ var RECONNECTION_DELAY = 1e3;
8422
+ var RECONNECTION_DELAY_MAX = 3e4;
8423
+ var SERVER_CLOSE_RECONNECT_SPREAD = 1e4;
8424
+ var spreadReconnectAfterServerClose = (socket) => {
8425
+ const manager = socket.io;
8426
+ if (typeof manager?.reconnectionDelay !== "function") return;
8427
+ socket.on("disconnect", (reason) => {
8428
+ if (reason === "transport close") {
8429
+ manager.reconnectionDelay(RECONNECTION_DELAY + Math.random() * SERVER_CLOSE_RECONNECT_SPREAD);
8430
+ }
8431
+ });
8432
+ socket.on("connect", () => manager.reconnectionDelay(RECONNECTION_DELAY));
8433
+ };
8309
8434
  function createSocketMethods(client) {
8310
8435
  const activeConnections = {};
8311
8436
  const debug = client.debug;
@@ -8359,12 +8484,12 @@
8359
8484
  query: { token },
8360
8485
  // Reconnection configuration for resilience
8361
8486
  reconnection: socketOptions.autoReconnect,
8362
- reconnectionAttempts: 10,
8363
- // Maximum reconnection attempts before giving up
8364
- reconnectionDelay: 1e3,
8365
- // Start with 1 second delay
8366
- reconnectionDelayMax: 3e4,
8367
- // Max delay of 30 seconds between attempts
8487
+ // Never give up: the server may refuse connections for a while (busy, or a deploy draining), and after a
8488
+ // final failure socket.io stops for good without telling the app (the manager's 'reconnect_failed' never
8489
+ // reaches socket listeners). Retries settle at one every ~30s.
8490
+ reconnectionAttempts: Infinity,
8491
+ reconnectionDelay: RECONNECTION_DELAY,
8492
+ reconnectionDelayMax: RECONNECTION_DELAY_MAX,
8368
8493
  randomizationFactor: 0.5,
8369
8494
  // Add jitter to avoid thundering herd problem
8370
8495
  // Connection timeout
@@ -8387,11 +8512,19 @@
8387
8512
  listeners: {}
8388
8513
  };
8389
8514
  activeConnections[channel] = socketChannel;
8515
+ spreadReconnectAfterServerClose(socket);
8390
8516
  return new Promise((resolve, reject) => {
8391
8517
  let settled = false;
8518
+ let hasConnected = false;
8392
8519
  socket.on("connect", () => {
8393
8520
  _log(`Connected to channel: ${channel}`);
8394
8521
  activeConnections[channel] = socketChannel;
8522
+ if (hasConnected) {
8523
+ _log(`Reconnected to channel ${channel}`);
8524
+ const reconnectListeners = socketChannel.listeners["reconnect"] || /* @__PURE__ */ new Set();
8525
+ reconnectListeners.forEach((listener) => listener({ type: "reconnect" }));
8526
+ }
8527
+ hasConnected = true;
8395
8528
  if (!settled) {
8396
8529
  settled = true;
8397
8530
  resolve(socketChannel);
@@ -8404,15 +8537,6 @@
8404
8537
  resolve(socketChannel);
8405
8538
  }
8406
8539
  });
8407
- socket.on("reconnect_attempt", (attempt) => {
8408
- _log(`Reconnection attempt ${attempt} for channel: ${channel}`);
8409
- });
8410
- socket.on("reconnect", (attempt) => {
8411
- _log(`Reconnected to channel ${channel} after ${attempt} attempts`);
8412
- activeConnections[channel] = socketChannel;
8413
- const reconnectListeners = socketChannel.listeners["reconnect"] || /* @__PURE__ */ new Set();
8414
- reconnectListeners.forEach((listener) => listener({ type: "reconnect", attempt }));
8415
- });
8416
8540
  socket.on("reconnect_failed", () => {
8417
8541
  _log(`Reconnection failed for channel ${channel} after maximum attempts`);
8418
8542
  const eventListeners = socketChannel.listeners["reconnect_failed"] || /* @__PURE__ */ new Set();
@@ -8492,9 +8616,10 @@
8492
8616
  query: { publicToken },
8493
8617
  // Reconnection configuration for resilience
8494
8618
  reconnection: socketOptions.autoReconnect,
8495
- reconnectionAttempts: 10,
8496
- reconnectionDelay: 1e3,
8497
- reconnectionDelayMax: 3e4,
8619
+ reconnectionAttempts: Infinity,
8620
+ // as connect(): never give up silently
8621
+ reconnectionDelay: RECONNECTION_DELAY,
8622
+ reconnectionDelayMax: RECONNECTION_DELAY_MAX,
8498
8623
  randomizationFactor: 0.5,
8499
8624
  // Connection timeout
8500
8625
  timeout: 2e4,
@@ -8509,6 +8634,7 @@
8509
8634
  channel,
8510
8635
  listeners: {}
8511
8636
  };
8637
+ spreadReconnectAfterServerClose(socket);
8512
8638
  return new Promise((resolve, reject) => {
8513
8639
  socket.on("connect", () => {
8514
8640
  _log(`Connected to public channel: ${channel}`);
@@ -8519,12 +8645,6 @@
8519
8645
  _log(`Connection error for public channel ${channel}:`, error);
8520
8646
  reject(error);
8521
8647
  });
8522
- socket.on("reconnect_attempt", (attempt) => {
8523
- _log(`Reconnection attempt ${attempt} for public channel: ${channel}`);
8524
- });
8525
- socket.on("reconnect", (attempt) => {
8526
- _log(`Reconnected to public channel ${channel} after ${attempt} attempts`);
8527
- });
8528
8648
  socket.on("reconnect_failed", () => {
8529
8649
  _log(`Reconnection failed for public channel ${channel} after maximum attempts`);
8530
8650
  const eventListeners = socketChannel.listeners["reconnect_failed"] || /* @__PURE__ */ new Set();
@@ -9665,6 +9785,40 @@
9665
9785
  endpoint: `/v1/devices/${deviceId}`,
9666
9786
  sendJWT: true
9667
9787
  });
9788
+ },
9789
+ /**
9790
+ * Register or refresh an iOS upload Live Activity, so the API carries it on by push through post-processing
9791
+ * while the app is suspended. Send the activity's push token and the app's view of the batch; send it again
9792
+ * as the batch changes. Requires authentication.
9793
+ * @param {string} activityId - ActivityKit's id for the activity.
9794
+ * @param {RegisterLiveActivityBody} body - Push token, APNs environment and the batch's files.
9795
+ * @returns {Promise<LiveActivityRegistration>} The activity id and the batch's stage.
9796
+ */
9797
+ async registerLiveActivity(activityId, body) {
9798
+ if (!activityId) {
9799
+ throw new Error("activityId is required.");
9800
+ }
9801
+ return client._request({
9802
+ method: "PUT",
9803
+ endpoint: `/v1/devices/live-activities/${activityId}`,
9804
+ body,
9805
+ sendJWT: true
9806
+ });
9807
+ },
9808
+ /**
9809
+ * Stop following an upload Live Activity (the app ended it). Requires authentication.
9810
+ * @param {string} activityId - ActivityKit's id for the activity.
9811
+ * @returns {Promise<void>}
9812
+ */
9813
+ async endLiveActivity(activityId) {
9814
+ if (!activityId) {
9815
+ throw new Error("activityId is required.");
9816
+ }
9817
+ return client._request({
9818
+ method: "DELETE",
9819
+ endpoint: `/v1/devices/live-activities/${activityId}`,
9820
+ sendJWT: true
9821
+ });
9668
9822
  }
9669
9823
  };
9670
9824
  }
@@ -10331,6 +10485,10 @@
10331
10485
  /**
10332
10486
  * Revoke the bot's current API key and issue a new one.
10333
10487
  * The new raw key is returned once.
10488
+ *
10489
+ * The replacement carries the old key's scopes verbatim, so this is not a
10490
+ * way to pick up scopes added to the registry since the key was minted —
10491
+ * `updateBotKeyScopes` is.
10334
10492
  */
10335
10493
  async rotateBotKey(workspaceId, botId) {
10336
10494
  if (!workspaceId) throw new Error("workspaceId is required.");
@@ -10341,6 +10499,65 @@
10341
10499
  sendJWT: true
10342
10500
  });
10343
10501
  },
10502
+ /**
10503
+ * Mint an ADDITIONAL API key for the bot, up to 5 live keys.
10504
+ *
10505
+ * Unlike `rotateBotKey`, the bot's existing keys keep working — which is
10506
+ * what makes a zero-downtime changeover possible: mint, move traffic over,
10507
+ * then revoke the old key. The raw key is returned once.
10508
+ */
10509
+ async createBotKey(workspaceId, botId, keyData) {
10510
+ if (!workspaceId) throw new Error("workspaceId is required.");
10511
+ if (!botId) throw new Error("botId is required.");
10512
+ if (!keyData?.name) throw new Error("name is required.");
10513
+ return client._request({
10514
+ method: "POST",
10515
+ endpoint: `/v1/workspaces/${workspaceId}/bots/${botId}/keys`,
10516
+ body: keyData,
10517
+ sendJWT: true
10518
+ });
10519
+ },
10520
+ /**
10521
+ * Replace the scopes on one of the bot's API keys, in place.
10522
+ *
10523
+ * A key's scopes are a snapshot taken when it was minted, and the registry
10524
+ * grows — a key created before a scope existed cannot hold it. Rotation is
10525
+ * not a substitute: `rotateBotKey` copies the old scope set onto the
10526
+ * replacement, so a stale key stays stale through every rotation.
10527
+ *
10528
+ * This matters most for keys minted with `scopes` omitted, which means
10529
+ * "the full registry" as it stood that day, not "whatever the full registry
10530
+ * becomes".
10531
+ *
10532
+ * The secret is unchanged — every caller configured with this key keeps
10533
+ * working, which is the whole point. Requires `canManageBots`.
10534
+ */
10535
+ async updateBotKeyScopes(workspaceId, botId, keyId, data) {
10536
+ if (!workspaceId) throw new Error("workspaceId is required.");
10537
+ if (!botId) throw new Error("botId is required.");
10538
+ if (!keyId) throw new Error("keyId is required.");
10539
+ return client._request({
10540
+ method: "PATCH",
10541
+ endpoint: `/v1/workspaces/${workspaceId}/bots/${botId}/keys/${keyId}`,
10542
+ body: data,
10543
+ sendJWT: true
10544
+ });
10545
+ },
10546
+ /**
10547
+ * Revoke one of the bot's API keys, leaving its others working.
10548
+ * A revoked key stops authenticating immediately and frees a slot
10549
+ * against the 5-key cap.
10550
+ */
10551
+ async revokeBotKey(workspaceId, botId, keyId) {
10552
+ if (!workspaceId) throw new Error("workspaceId is required.");
10553
+ if (!botId) throw new Error("botId is required.");
10554
+ if (!keyId) throw new Error("keyId is required.");
10555
+ return client._request({
10556
+ method: "DELETE",
10557
+ endpoint: `/v1/workspaces/${workspaceId}/bots/${botId}/keys/${keyId}`,
10558
+ sendJWT: true
10559
+ });
10560
+ },
10344
10561
  /**
10345
10562
  * Request signed URL data to upload a new avatar for the bot.
10346
10563
  * Caller multipart-uploads the file to S3 using the returned `signedUrlData`,
@@ -10782,6 +10999,27 @@
10782
10999
  bypassCache: true
10783
11000
  });
10784
11001
  },
11002
+ /**
11003
+ * Replace the scopes on one of the caller's Personal Access Tokens.
11004
+ *
11005
+ * `scopes` is the complete new set, not a delta. This exists because
11006
+ * the scope registry grows over time: a token minted before a scope
11007
+ * existed cannot hold it, and without this the only remedy is minting
11008
+ * a replacement and reconfiguring everywhere the old one is used.
11009
+ *
11010
+ * The change takes effect on the token's very next request. Scopes
11011
+ * remain a ceiling, never a floor — widening a token never lets it do
11012
+ * anything its owner cannot already do.
11013
+ */
11014
+ async updateTokenScopes(tokenId, data) {
11015
+ if (!tokenId) throw new Error("tokenId is required.");
11016
+ return client._request({
11017
+ method: "PATCH",
11018
+ endpoint: `/v1/tokens/${tokenId}`,
11019
+ body: data,
11020
+ sendJWT: true
11021
+ });
11022
+ },
10785
11023
  /**
10786
11024
  * Revoke one of the caller's Personal Access Tokens. The revocation
10787
11025
  * is immediate — the token will return 401 on the very next request.
@@ -10797,6 +11035,38 @@
10797
11035
  };
10798
11036
  }
10799
11037
 
11038
+ // src/routes/oauthGrant.ts
11039
+ function createOAuthGrantMethods(client) {
11040
+ return {
11041
+ /**
11042
+ * List the applications the caller has authorised, newest first.
11043
+ * Expired grants are omitted by the server.
11044
+ */
11045
+ async listGrants() {
11046
+ const res = await client._request({
11047
+ method: "GET",
11048
+ endpoint: "/v1/oauth-grants",
11049
+ sendJWT: true,
11050
+ bypassCache: true
11051
+ });
11052
+ return res.results;
11053
+ },
11054
+ /**
11055
+ * Withdraw an application's access: the grant and every token issued
11056
+ * under it. An access token already in flight stays valid until it
11057
+ * expires, so revocation is not instantaneous for a request under way.
11058
+ */
11059
+ async revokeGrant(grantId) {
11060
+ if (!grantId) throw new Error("grantId is required.");
11061
+ return client._request({
11062
+ method: "DELETE",
11063
+ endpoint: `/v1/oauth-grants/${grantId}`,
11064
+ sendJWT: true
11065
+ });
11066
+ }
11067
+ };
11068
+ }
11069
+
10800
11070
  // src/routes/webhook.ts
10801
11071
  function createWebhookMethods(client) {
10802
11072
  return {
@@ -10989,10 +11259,10 @@
10989
11259
 
10990
11260
  // src/version.ts
10991
11261
  var SDK_VERSION = {
10992
- version: "1.4.0",
10993
- buildTimestamp: "2026-10-03T16:23:07.694Z",
10994
- buildHash: "60ddbec0797c9d1bdf96aaf49b69dda5",
10995
- gitCommit: "c000da4",
11262
+ version: "1.4.2",
11263
+ buildTimestamp: "2026-10-13T14:29:32.506Z",
11264
+ buildHash: "4d2cf795aed2effc13ea74e85309a692",
11265
+ gitCommit: "6c603cf",
10996
11266
  dirty: false
10997
11267
  };
10998
11268
 
@@ -11048,6 +11318,7 @@
11048
11318
  this.invalidateCacheOnMutation = options.invalidateCacheOnMutation === void 0 ? true : options.invalidateCacheOnMutation;
11049
11319
  this._onUnauthorized = options.onUnauthorized;
11050
11320
  this._onMaintenance = options.onMaintenance;
11321
+ this._onTokensChanged = options.onTokensChanged;
11051
11322
  this._apiKey = options.apiKey || null;
11052
11323
  if (this.browserMode && !this._apiKey) {
11053
11324
  this._loadTokens();
@@ -11087,6 +11358,7 @@
11087
11358
  this.credits = createCreditsMethods(this);
11088
11359
  this.scratch = createScratchMethods(this);
11089
11360
  this.token = createTokenMethods(this);
11361
+ this.oauthGrant = createOAuthGrantMethods(this);
11090
11362
  this.webhook = createWebhookMethods(this);
11091
11363
  this.supportTicket = createSupportTicketMethods(this);
11092
11364
  }
@@ -11326,6 +11598,39 @@
11326
11598
  console.error("Failed to save tokens to localStorage:", e);
11327
11599
  }
11328
11600
  }
11601
+ if (this._onTokensChanged) {
11602
+ try {
11603
+ this._onTokensChanged(accessToken || refreshToken ? this.getSession() : null);
11604
+ } catch (e) {
11605
+ console.error("onTokensChanged handler threw:", e);
11606
+ }
11607
+ }
11608
+ }
11609
+ /**
11610
+ * Returns the current session (tokens and expiries), or null when signed out.
11611
+ * @public
11612
+ */
11613
+ getSession() {
11614
+ if (!this._accessToken && !this._refreshTokenValue) return null;
11615
+ return {
11616
+ accessToken: this._accessToken,
11617
+ refreshToken: this._refreshTokenValue,
11618
+ accessTokenExpiry: this._accessTokenExpiry,
11619
+ refreshTokenExpiry: this._refreshTokenExpiry
11620
+ };
11621
+ }
11622
+ /**
11623
+ * Restores a session previously captured through `onTokensChanged` /
11624
+ * `getSession()` — for hosts that persist tokens outside localStorage.
11625
+ * Does not fire `onTokensChanged`. A missing or expired access token is
11626
+ * refreshed on the next authenticated request.
11627
+ * @public
11628
+ */
11629
+ restoreSession(session) {
11630
+ this._accessToken = session?.accessToken ?? null;
11631
+ this._refreshTokenValue = session?.refreshToken ?? null;
11632
+ this._accessTokenExpiry = session?.accessTokenExpiry ?? null;
11633
+ this._refreshTokenExpiry = session?.refreshTokenExpiry ?? null;
11329
11634
  }
11330
11635
  /**
11331
11636
  * Retrieves the current access token.