@whereby.com/browser-sdk 2.0.0-alpha → 2.0.0-alpha2

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 (72) hide show
  1. package/dist/lib.cjs.js +5467 -0
  2. package/dist/lib.esm.js +5451 -0
  3. package/dist/types.d.ts +104 -0
  4. package/dist/v2-alpha2.js +105 -0
  5. package/package.json +6 -1
  6. package/.eslintrc +0 -23
  7. package/.github/actions/build/action.yml +0 -17
  8. package/.github/workflows/deploy.yml +0 -102
  9. package/.github/workflows/test.yml +0 -24
  10. package/.prettierignore +0 -7
  11. package/.prettierrc +0 -4
  12. package/.storybook/main.cjs +0 -16
  13. package/.storybook/preview.js +0 -9
  14. package/jest.config.js +0 -6
  15. package/rollup.config.js +0 -70
  16. package/src/lib/RoomConnection.ts +0 -516
  17. package/src/lib/RoomParticipant.ts +0 -77
  18. package/src/lib/__tests__/embed.unit.ts +0 -77
  19. package/src/lib/api/ApiClient.ts +0 -111
  20. package/src/lib/api/Credentials.ts +0 -45
  21. package/src/lib/api/HttpClient.ts +0 -95
  22. package/src/lib/api/MultipartHttpClient.ts +0 -53
  23. package/src/lib/api/OrganizationApiClient.ts +0 -64
  24. package/src/lib/api/Response.ts +0 -34
  25. package/src/lib/api/credentialsService/index.ts +0 -159
  26. package/src/lib/api/credentialsService/test/index.spec.ts +0 -181
  27. package/src/lib/api/deviceService/index.ts +0 -42
  28. package/src/lib/api/deviceService/tests/index.spec.ts +0 -74
  29. package/src/lib/api/extractUtils.ts +0 -160
  30. package/src/lib/api/index.ts +0 -8
  31. package/src/lib/api/localStorageWrapper/index.ts +0 -15
  32. package/src/lib/api/models/Account.ts +0 -48
  33. package/src/lib/api/models/Meeting.ts +0 -42
  34. package/src/lib/api/models/Organization.ts +0 -186
  35. package/src/lib/api/models/Room.ts +0 -44
  36. package/src/lib/api/models/account/EmbeddedFreeTierStatus.ts +0 -34
  37. package/src/lib/api/models/tests/Account.spec.ts +0 -128
  38. package/src/lib/api/models/tests/Organization.spec.ts +0 -161
  39. package/src/lib/api/models/tests/Room.spec.ts +0 -74
  40. package/src/lib/api/modules/AbstractStore.ts +0 -18
  41. package/src/lib/api/modules/ChromeStorageStore.ts +0 -44
  42. package/src/lib/api/modules/LocalStorageStore.ts +0 -57
  43. package/src/lib/api/modules/tests/ChromeStorageStore.spec.ts +0 -67
  44. package/src/lib/api/modules/tests/LocalStorageStore.spec.ts +0 -79
  45. package/src/lib/api/modules/tests/__mocks__/storage.ts +0 -24
  46. package/src/lib/api/organizationService/index.ts +0 -284
  47. package/src/lib/api/organizationService/tests/index.spec.ts +0 -781
  48. package/src/lib/api/organizationServiceCache/index.ts +0 -28
  49. package/src/lib/api/organizationServiceCache/tests/index.spec.ts +0 -101
  50. package/src/lib/api/parameterAssertUtils.ts +0 -166
  51. package/src/lib/api/roomService/index.ts +0 -310
  52. package/src/lib/api/roomService/tests/index.spec.ts +0 -668
  53. package/src/lib/api/test/ApiClient.spec.ts +0 -139
  54. package/src/lib/api/test/HttpClient.spec.ts +0 -120
  55. package/src/lib/api/test/MultipartHttpClient.spec.ts +0 -145
  56. package/src/lib/api/test/OrganizationApiClient.spec.ts +0 -132
  57. package/src/lib/api/test/extractUtils.spec.ts +0 -357
  58. package/src/lib/api/test/helpers.ts +0 -41
  59. package/src/lib/api/test/parameterAssertUtils.spec.ts +0 -265
  60. package/src/lib/api/types.ts +0 -6
  61. package/src/lib/embed.ts +0 -172
  62. package/src/lib/index.ts +0 -3
  63. package/src/lib/react/VideoElement.tsx +0 -16
  64. package/src/lib/react/index.ts +0 -3
  65. package/src/lib/react/useLocalMedia.ts +0 -25
  66. package/src/lib/react/useRoomConnection.ts +0 -92
  67. package/src/lib/reducer.ts +0 -142
  68. package/src/stories/custom-ui.stories.tsx +0 -133
  69. package/src/stories/prebuilt-ui.stories.tsx +0 -131
  70. package/src/stories/styles.css +0 -74
  71. package/src/types.d.ts +0 -175
  72. package/tsconfig.json +0 -30
@@ -1,111 +0,0 @@
1
- import assert from "assert";
2
- import nodeBtoa from "btoa";
3
- import HttpClient, { HttpClientRequestConfig } from "./HttpClient";
4
- import MultipartHttpClient from "./MultipartHttpClient";
5
- import { assertString } from "./parameterAssertUtils";
6
- import Credentials from "./Credentials";
7
- import Response from "./Response";
8
-
9
- let btoa: (str: string) => string;
10
- if (typeof window === "object") {
11
- btoa = window.btoa || nodeBtoa;
12
- } else if (typeof global === "object") {
13
- btoa = global.btoa || nodeBtoa;
14
- } else {
15
- btoa = nodeBtoa;
16
- }
17
-
18
- /**
19
- * Create an object, which should be merged into the request header
20
- * object, which deals with the header's authorisation
21
- */
22
- function _getAuthHeader(credentials: Credentials | null) {
23
- if (credentials && credentials.credentials) {
24
- const btoaStr = `${credentials.credentials.uuid}:${credentials.hmac}`;
25
- return { Authorization: `Basic ${btoa(btoaStr)}` };
26
- }
27
- return {};
28
- }
29
-
30
- interface AuthenticatedHttpClientOptions {
31
- httpClient: HttpClient;
32
- fetchDeviceCredentials: () => Promise<Credentials | null>;
33
- }
34
-
35
- const noCredentials: AuthenticatedHttpClientOptions["fetchDeviceCredentials"] = () => Promise.resolve(null);
36
-
37
- class AuthenticatedHttpClient {
38
- private _httpClient: AuthenticatedHttpClientOptions["httpClient"];
39
- private _fetchDeviceCredentials: AuthenticatedHttpClientOptions["fetchDeviceCredentials"];
40
-
41
- constructor({ httpClient, fetchDeviceCredentials }: AuthenticatedHttpClientOptions) {
42
- this._httpClient = httpClient;
43
- this._fetchDeviceCredentials = fetchDeviceCredentials;
44
- }
45
-
46
- request(url: string, options: HttpClientRequestConfig): Promise<Response> {
47
- return this._fetchDeviceCredentials().then((credentials) => {
48
- const headers = Object.assign({}, options.headers, _getAuthHeader(credentials), {
49
- "X-Appearin-Device-Platform": "web",
50
- });
51
-
52
- const httpClientOptions = Object.assign({}, options, { headers });
53
-
54
- return this._httpClient.request(url, httpClientOptions);
55
- });
56
- }
57
- }
58
-
59
- interface ApiClientOptions {
60
- baseUrl?: string;
61
- fetchDeviceCredentials?: AuthenticatedHttpClientOptions["fetchDeviceCredentials"];
62
- }
63
- /**
64
- * Class used for all Whereby API calls.
65
- */
66
- export default class ApiClient {
67
- authenticatedHttpClient: AuthenticatedHttpClient;
68
- authenticatedFormDataHttpClient: MultipartHttpClient;
69
-
70
- /**
71
- * Create an ApiClient instance.
72
- */
73
- constructor({
74
- baseUrl = "https://api.appearin.net",
75
- fetchDeviceCredentials = noCredentials,
76
- }: ApiClientOptions = {}) {
77
- assertString(baseUrl, "baseUrl");
78
- assert.ok(typeof fetchDeviceCredentials === "function", "fetchDeviceCredentials<Function> is required");
79
-
80
- this.authenticatedHttpClient = new AuthenticatedHttpClient({
81
- httpClient: new HttpClient({
82
- baseUrl,
83
- }),
84
- fetchDeviceCredentials,
85
- });
86
-
87
- this.authenticatedFormDataHttpClient = new MultipartHttpClient({ httpClient: this.authenticatedHttpClient });
88
- }
89
-
90
- /**
91
- * Wrapper for the fetch API
92
- */
93
- request(url: string, options: HttpClientRequestConfig): Promise<Response> {
94
- assertString(url, "url");
95
- assert.equal(url[0], "/", 'url<String> only accepts relative URLs beginning with "/".');
96
- assert.ok(options, "options are required");
97
-
98
- return this.authenticatedHttpClient.request(url, options);
99
- }
100
-
101
- /**
102
- * Performs a multipart request where data is multipart/form-data encoded.
103
- */
104
- requestMultipart(url: string, options: HttpClientRequestConfig): Promise<Response> {
105
- assertString(url, "url");
106
- assert.equal(url[0], "/", 'url<String> only accepts relative URLs beginning with "/".');
107
- assert.ok(options, "options are required");
108
-
109
- return this.authenticatedFormDataHttpClient.request(url, options);
110
- }
111
- }
@@ -1,45 +0,0 @@
1
- import { extractJson, extractNullOrString, extractString } from "./extractUtils";
2
- import { Json } from "./Response";
3
-
4
- interface CredentialsOptions {
5
- uuid: string;
6
- hmac: string;
7
- userId?: string;
8
- }
9
-
10
- export default class Credentials {
11
- credentials: {
12
- uuid: CredentialsOptions["uuid"];
13
- };
14
-
15
- hmac: CredentialsOptions["hmac"];
16
- userId: CredentialsOptions["userId"];
17
-
18
- constructor(
19
- uuid: CredentialsOptions["uuid"],
20
- hmac: CredentialsOptions["hmac"],
21
- userId: CredentialsOptions["userId"] = undefined
22
- ) {
23
- this.credentials = {
24
- uuid,
25
- };
26
- this.hmac = hmac;
27
- this.userId = userId;
28
- }
29
-
30
- toJson(): Json {
31
- return {
32
- credentials: this.credentials,
33
- hmac: this.hmac,
34
- ...(this.userId && { userId: this.userId }),
35
- };
36
- }
37
-
38
- static fromJson(json: Json): Credentials {
39
- return new Credentials(
40
- extractString(extractJson(json, "credentials"), "uuid"),
41
- extractString(json, "hmac"),
42
- extractNullOrString(json, "userId") || undefined
43
- );
44
- }
45
- }
@@ -1,95 +0,0 @@
1
- import assert from "assert";
2
- import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios";
3
- import Response, { ErrorResponseObject } from "./Response";
4
- import { assertString } from "./parameterAssertUtils";
5
-
6
- export type HttpClientRequestConfig =
7
- | AxiosRequestConfig
8
- | { [key: string]: any };
9
-
10
- export interface IHttpClient {
11
- request(url: string, options: HttpClientRequestConfig): Promise<Response>;
12
- }
13
-
14
- function _getAbsoluteUrl({ baseUrl, url }: { baseUrl?: string; url: string }): string {
15
- assert.ok(typeof url === "string", "url<String> is required");
16
- return baseUrl ? baseUrl + url : url;
17
- }
18
-
19
- /**
20
- * Class used for making http calls. This is just a pure
21
- * wrapper around the http lib that we decide to use,
22
- * so that we can switch implementations.
23
- */
24
- export default class HttpClient implements IHttpClient {
25
- _baseUrl: string;
26
- /**
27
- * Creates an HttpClient instance.
28
- *
29
- * @param {string} [baseUrl] - The base URL where all requests are made.
30
- */
31
- constructor({ baseUrl }: { baseUrl: string }) {
32
- assertString(baseUrl, "baseUrl");
33
-
34
- this._baseUrl = baseUrl;
35
- }
36
-
37
- private _requestAxios(url: string, options: HttpClientRequestConfig): Promise<AxiosResponse> {
38
- const axiosOptions = Object.assign({}, options, {
39
- url,
40
- baseURL: this._baseUrl,
41
- });
42
-
43
- return axios.request(axiosOptions);
44
- }
45
-
46
- /**
47
- * Wrapper for the axios API
48
- *
49
- * @param {string} url - Required. URL (appended to base URL) where API call will be made
50
- * @param {object} options - Required. Contains the data needed for the fetch API
51
- * @return {Promise<Response>} - A promise which will return a Response object (https://developer.mozilla.org/en-US/docs/Web/API/Response)
52
- */
53
- request(url: string, options: HttpClientRequestConfig): Promise<Response> {
54
- assertString(url, "url");
55
- assert.equal(url[0], "/", 'url<String> only accepts relative URLs beginning with "/".');
56
- assert.ok(options, "options are required");
57
-
58
- return this._requestAxios(url, options)
59
- .then((response) => {
60
- const { data, headers, status, statusText, config } = response;
61
- const requestUrl =
62
- config && config.url ? _getAbsoluteUrl({ baseUrl: config.baseURL, url: config.url }) : null;
63
-
64
- return new Response({
65
- data,
66
- headers,
67
- status,
68
- statusText,
69
- url: requestUrl,
70
- });
71
- })
72
- .catch((error: AxiosError) => {
73
- const responseObject = error.response;
74
-
75
- if (!responseObject) {
76
- // Either server error or something else.
77
- throw new Error("Could not make the request.");
78
- }
79
-
80
- const { data, headers, status, statusText, config } = responseObject as ErrorResponseObject;
81
- const requestUrl =
82
- config && config.url ? _getAbsoluteUrl({ baseUrl: config.baseURL, url: config.url }) : null;
83
-
84
- return Promise.reject(
85
- new Response({
86
- data,
87
- headers,
88
- status,
89
- statusText,
90
- url: requestUrl,
91
- })
92
- );
93
- });
94
- }
95
- }
@@ -1,53 +0,0 @@
1
- import assert from "assert";
2
- import { HttpClientRequestConfig, IHttpClient } from "./HttpClient";
3
- import Response from "./Response";
4
-
5
- /**
6
- * ApiClient for doing multipart/form-data requests.
7
- */
8
- export default class MultipartHttpClient implements IHttpClient {
9
- _httpClient: IHttpClient;
10
-
11
- constructor({ httpClient }: { httpClient: IHttpClient }) {
12
- assert.ok(httpClient, "httpClient is required");
13
-
14
- this._httpClient = httpClient;
15
- }
16
-
17
- /**
18
- * Convert the provided object to a FormData object containing the same keys and values.
19
- * @param {object} data - the data to convert.
20
- * @returns {FormData}
21
- */
22
- static dataToFormData(data: Record<string, string>): FormData {
23
- assert.ok(data, "data is required");
24
-
25
- const fd = new FormData();
26
- Object.keys(data).forEach((key) => {
27
- const value = data[key];
28
- fd.append(key, value);
29
- });
30
- return fd;
31
- }
32
-
33
- /**
34
- * Request a resource using multipart/form-data encoding.
35
- *
36
- * @param {string} url - the url to request
37
- * @param {object} options - Required. Contains the data needed for the fetch API
38
- * @return {Promise<Response>} - A promise which will return a Response object (https://developer.mozilla.org/en-US/docs/Web/API/Response)
39
- */
40
- request(url: string, options: HttpClientRequestConfig = {}): Promise<Response> {
41
- const headers = Object.assign(options.headers || {}, {
42
- "Content-Type": undefined,
43
- });
44
-
45
- return this._httpClient.request(
46
- url,
47
- Object.assign(options, {
48
- headers,
49
- transformRequest: MultipartHttpClient.dataToFormData,
50
- })
51
- );
52
- }
53
- }
@@ -1,64 +0,0 @@
1
- import ApiClient from "./ApiClient";
2
- import assert from "assert";
3
- import { assertInstanceOf, assertString } from "./parameterAssertUtils";
4
- import { HttpClientRequestConfig } from "./HttpClient";
5
- import Response from "./Response";
6
- import Organization from "./models/Organization";
7
-
8
- const noOrganization = () => Promise.resolve(undefined);
9
-
10
- export type FetchOrganizationFunction = () => Promise<Organization | undefined>;
11
-
12
- /**
13
- * Class used for all Whereby organization API calls.
14
- */
15
- export default class OrganizationApiClient {
16
- private _apiClient: ApiClient;
17
- private _fetchOrganization: FetchOrganizationFunction;
18
- /**
19
- * Create an OrganizationApiClient instance.
20
- *
21
- * @param {ApiClient} [apiClient] - The apiClient to use.
22
- * @param {Function} [fetchOrganization] - function that returns a promise with the organization.
23
- */
24
- constructor({
25
- apiClient,
26
- fetchOrganization = noOrganization,
27
- }: {
28
- apiClient: ApiClient;
29
- fetchOrganization?: FetchOrganizationFunction;
30
- }) {
31
- this._apiClient = assertInstanceOf(apiClient, ApiClient);
32
- assert.ok(typeof fetchOrganization === "function", "fetchOrganization<Function> is required");
33
-
34
- this._fetchOrganization = fetchOrganization;
35
- this._apiClient = apiClient;
36
- }
37
-
38
- _callRequestMethod(
39
- method: "request" | "requestMultipart",
40
- url: string,
41
- options: HttpClientRequestConfig
42
- ): Promise<Response> {
43
- assertString(url, "url");
44
- assert.equal(url[0], "/", 'url<String> only accepts relative URLs beginning with "/".');
45
- assert.ok(options, "options are required");
46
- return this._fetchOrganization().then((organization) => {
47
- if (!organization) {
48
- return this._apiClient[method](url, options);
49
- }
50
-
51
- const { organizationId } = organization;
52
-
53
- return this._apiClient[method](`/organizations/${encodeURIComponent(organizationId)}${url}`, options);
54
- });
55
- }
56
-
57
- request(url: string, options: HttpClientRequestConfig): Promise<Response> {
58
- return this._callRequestMethod("request", url, options);
59
- }
60
-
61
- requestMultipart(url: string, options: HttpClientRequestConfig): Promise<Response> {
62
- return this._callRequestMethod("requestMultipart", url, options);
63
- }
64
- }
@@ -1,34 +0,0 @@
1
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2
- export type Json = string | number | boolean | null | Array<Json> | { [key: string]: Json };
3
-
4
- export type ErrorResponseObject = {
5
- data?: Json;
6
- headers?: Record<string, any>;
7
- status?: number;
8
- statusText?: string;
9
- config?: { url?: string; baseURL?: string } | null;
10
- };
11
-
12
- interface ResponseOptions {
13
- data?: Json;
14
- headers?: Record<string, any>;
15
- status?: number;
16
- statusText?: string;
17
- url?: string | null;
18
- }
19
-
20
- export default class Response {
21
- data: Json;
22
- headers: Record<string, unknown>;
23
- status: number;
24
- statusText: string;
25
- url: string | null;
26
-
27
- constructor(initialValues: ResponseOptions = {}) {
28
- this.data = initialValues.data === undefined ? {} : initialValues.data;
29
- this.headers = initialValues.headers || {};
30
- this.status = initialValues.status || 200;
31
- this.statusText = initialValues.statusText || "OK";
32
- this.url = initialValues.url || null;
33
- }
34
- }
@@ -1,159 +0,0 @@
1
- import EventEmitter from "events";
2
-
3
- import DeviceService from "../deviceService/index";
4
- import AbstractStore from "../modules/AbstractStore";
5
- import ChromeStorageStore from "../modules/ChromeStorageStore";
6
- import LocalStorageStore from "../modules/LocalStorageStore";
7
- import { assertInstanceOf } from "../parameterAssertUtils";
8
- import ApiClient from "../ApiClient";
9
- import localStorage from "../localStorageWrapper";
10
- import { Credentials } from "..";
11
-
12
- /**
13
- * Events triggered by this service
14
- */
15
- export const events = {
16
- CREDENTIALS_SAVED: "credentials_saved",
17
- };
18
-
19
- export default class CredentialsService extends EventEmitter {
20
- _deviceService: DeviceService;
21
- _credentialsStore: AbstractStore;
22
- credentialsPromise?: Promise<Credentials | null>;
23
-
24
- /**
25
- * Service to manage Whereby's Rest API credentials.
26
- *
27
- * @param {ObjectStore} credentialsStore - Store to manage the credentials.
28
- */
29
- constructor({
30
- deviceService,
31
- credentialsStore,
32
- }: {
33
- deviceService: DeviceService;
34
- credentialsStore: AbstractStore;
35
- }) {
36
- super();
37
- this._deviceService = assertInstanceOf(deviceService, DeviceService);
38
- this._credentialsStore = credentialsStore;
39
- }
40
-
41
- static create({
42
- baseUrl,
43
- storeName = "CredentialsStorage",
44
- storeType = "localStorage",
45
- }: {
46
- baseUrl: string;
47
- storeName?: string;
48
- storeType?: "localStorage" | "chromeStorage";
49
- }): CredentialsService {
50
- const deviceService = new DeviceService({
51
- apiClient: new ApiClient({ baseUrl }),
52
- });
53
-
54
- let credentialsStore = null;
55
-
56
- if (storeType === "localStorage") {
57
- credentialsStore = new LocalStorageStore(storeName, localStorage);
58
- } else if (storeType === "chromeStorage") {
59
- credentialsStore = new ChromeStorageStore(storeName, window["chrome"].storage.local);
60
- } else {
61
- throw new Error(`Unknown store type: ${storeType}`);
62
- }
63
-
64
- return new CredentialsService({
65
- deviceService,
66
- credentialsStore,
67
- });
68
- }
69
- /**
70
- * Contacts the REST API to get new credentials. DO NOT USE directly, call getCredentials() instead.
71
- *
72
- * @see getCredentials
73
- * @returns {Promise.<Credentials>} - Promise that resolves with the credentials.
74
- */
75
- _fetchNewCredentialsFromApi(): Promise<Credentials | null> {
76
- const credentialsStore = this._credentialsStore;
77
- return new Promise((resolve) => {
78
- const fetchCredentials = () => {
79
- this._deviceService
80
- .getCredentials()
81
- .then((credentials) => {
82
- return credentialsStore
83
- .save(credentials ? credentials.toJson() : null)
84
- .then(() => resolve(credentials));
85
- })
86
- .catch(() => {
87
- setTimeout(fetchCredentials, 2000);
88
- });
89
- };
90
- fetchCredentials();
91
- });
92
- }
93
-
94
- /**
95
- * Returns the current credentials without triggering an API request to get new ones.
96
- * If no credentials are currently available it will return null.
97
- *
98
- * @returns {?Credentials} - The credentials currently in use, null otherwise.
99
- */
100
- getCurrentCredentials(): Promise<Credentials | null> {
101
- return this._credentialsStore.loadOrDefault(null).then((json) => (json ? Credentials.fromJson(json) : null));
102
- }
103
-
104
- /**
105
- * Returns a promise that will contain the credentials for this client.
106
- * If no credentials are available in local storage, new ones will be fetched from the server.
107
- *
108
- * @returns {Promise.<Credentials>} - Promise that resolves with the credentials.
109
- */
110
- getCredentials(): Promise<Credentials | null> {
111
- if (!this.credentialsPromise) {
112
- this.credentialsPromise = this.getCurrentCredentials().then((storedCredentials) => {
113
- if (storedCredentials) {
114
- return storedCredentials;
115
- }
116
-
117
- return this._fetchNewCredentialsFromApi();
118
- });
119
- }
120
-
121
- return this.credentialsPromise;
122
- }
123
-
124
- /**
125
- * Saves new credentials which replace the existing ones and abort any pending request to get new ones.
126
- *
127
- * @param {Credentials} credentials - New credentials to store.
128
- */
129
- saveCredentials(credentials: Credentials): Promise<Credentials> {
130
- this.credentialsPromise = undefined;
131
- return this._credentialsStore.save(credentials.toJson()).then(() => {
132
- this.emit(events.CREDENTIALS_SAVED, credentials);
133
- return credentials;
134
- });
135
- }
136
-
137
- /**
138
- * It will set the userId for the current credentials.
139
- *
140
- * @param userId - The user id to set.
141
- */
142
- setUserId(userId: string | null): Promise<void> {
143
- // Used to ensure that the userId is changed if localStorage has been modified by another tab
144
- return this.getCurrentCredentials()
145
- .then((storedCredentials) => {
146
- if (!storedCredentials) {
147
- console.error("Illegal state: no credentials to set user id for."); // eslint-disable-line no-console
148
- }
149
-
150
- const userIdChangedFromLocalStorage = storedCredentials === null || storedCredentials.userId !== userId;
151
- if (!userIdChangedFromLocalStorage) {
152
- return undefined;
153
- }
154
-
155
- return this._credentialsStore.save(Object.assign({}, storedCredentials?.toJson(), { userId }));
156
- })
157
- .then(() => undefined);
158
- }
159
- }