@monterosa/sdk-identify-kit 2.0.0-rc.3 → 2.0.0-rc.4
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/api.d.ts +187 -173
- package/dist/bridge.d.ts +12 -3
- package/dist/credentials_store.d.ts +31 -0
- package/dist/identify.d.ts +4 -10
- package/dist/identify_options.d.ts +28 -0
- package/dist/identify_url.d.ts +25 -0
- package/dist/identity_options.d.ts +31 -0
- package/dist/index.cjs +444 -378
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +444 -378
- package/dist/index.js.map +1 -1
- package/dist/login_policy_store.d.ts +28 -0
- package/dist/types.d.ts +16 -43
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Emitter, createError, TaskQueue, withRetryAsync, memoizePromise, subscribe, MonterosaError, getErrorMessage } from '@monterosa/sdk-util';
|
|
1
|
+
import { Emitter, createError, subscribe, TaskQueue, withRetryAsync, memoizePromise, MonterosaError, getErrorMessage } from '@monterosa/sdk-util';
|
|
3
2
|
import { getParentApplication, sendSdkRequest, BridgeError, sendSdkMessage, onStateChanged, onSdkMessage, respondToSdkMessage } from '@monterosa/sdk-launcher-kit';
|
|
3
|
+
import { getDeviceId, Sdk, getSdk } from '@monterosa/sdk-core';
|
|
4
4
|
import { getConnect, connect, login as login$1, logout as logout$1, onConnected, onConnecting, onDisconnected } from '@monterosa/sdk-connect-kit';
|
|
5
5
|
import { fetchListings } from '@monterosa/sdk-interact-interop';
|
|
6
6
|
|
|
@@ -20,10 +20,8 @@ var IdentifyEvent;
|
|
|
20
20
|
IdentifyEvent["StateUpdated"] = "state_updated";
|
|
21
21
|
IdentifyEvent["LoginRequested"] = "login_requested";
|
|
22
22
|
IdentifyEvent["LogoutRequested"] = "logout_requested";
|
|
23
|
-
IdentifyEvent["SignatureUpdated"] = "signature_updated";
|
|
24
|
-
IdentifyEvent["UserdataUpdated"] = "userdata_updated";
|
|
25
23
|
IdentifyEvent["CredentialsUpdated"] = "credentials_updated";
|
|
26
|
-
IdentifyEvent["
|
|
24
|
+
IdentifyEvent["LoginPolicyUpdated"] = "login_policy_updated";
|
|
27
25
|
})(IdentifyEvent || (IdentifyEvent = {}));
|
|
28
26
|
/**
|
|
29
27
|
* Defines a set of error codes that may be encountered when using the
|
|
@@ -36,8 +34,6 @@ var IdentifyEvent;
|
|
|
36
34
|
* } catch (err) {
|
|
37
35
|
* if (err.code === IdentifyError.NoCredentials) {
|
|
38
36
|
* // handle missing credentials error
|
|
39
|
-
* } else if (err.code === IdentifyError.NotInitialised) {
|
|
40
|
-
* // handle initialization error
|
|
41
37
|
* } else {
|
|
42
38
|
* // handle other error types
|
|
43
39
|
* }
|
|
@@ -67,10 +63,6 @@ var IdentifyError;
|
|
|
67
63
|
* or have expired.
|
|
68
64
|
*/
|
|
69
65
|
IdentifyError["NoCredentials"] = "no_credentials";
|
|
70
|
-
/**
|
|
71
|
-
* Indicates the IdentifyKit has not been initialised properly.
|
|
72
|
-
*/
|
|
73
|
-
IdentifyError["NotInitialised"] = "not_initialised";
|
|
74
66
|
/**
|
|
75
67
|
* Indicates an error occurred in the parent app.
|
|
76
68
|
*/
|
|
@@ -95,7 +87,6 @@ const IdentifyErrorMessages = {
|
|
|
95
87
|
[IdentifyError.ExtensionApiError]: (error) => `Identify extension API returned an error: ${error}`,
|
|
96
88
|
[IdentifyError.ExtensionNotSetup]: () => 'Identify extension is not set up for this project',
|
|
97
89
|
[IdentifyError.NoCredentials]: () => 'Identify credentials are not set',
|
|
98
|
-
[IdentifyError.NotInitialised]: () => 'Identify instance is not initialised',
|
|
99
90
|
[IdentifyError.ParentAppError]: (error) => `Parent application error: ${error}`,
|
|
100
91
|
[IdentifyError.UnexpectedState]: (state) => `Unexpected LoginState: ${state}`,
|
|
101
92
|
[IdentifyError.NoParentApplication]: () => 'No parent application available for delegation',
|
|
@@ -107,14 +98,9 @@ var IdentifyAction;
|
|
|
107
98
|
IdentifyAction["Logout"] = "identifyLogout";
|
|
108
99
|
IdentifyAction["RequestLogin"] = "identifyRequestLogin";
|
|
109
100
|
IdentifyAction["RequestLogout"] = "identifyRequestLogout";
|
|
110
|
-
IdentifyAction["
|
|
111
|
-
IdentifyAction["GetSessionSignature"] = "identifyGetSessionSignature";
|
|
101
|
+
IdentifyAction["GetCredentials"] = "identifyGetCredentials";
|
|
112
102
|
IdentifyAction["SetCredentials"] = "identifySetCredentials";
|
|
113
103
|
IdentifyAction["ClearCredentials"] = "identifyClearCredentials";
|
|
114
|
-
IdentifyAction["OnStateUpdated"] = "identifyOnStateUpdated";
|
|
115
|
-
IdentifyAction["OnCredentialsUpdated"] = "identifyOnCredentialsUpdated";
|
|
116
|
-
IdentifyAction["OnUserDataUpdated"] = "identifyOnUserDataUpdated";
|
|
117
|
-
IdentifyAction["OnSessionSignatureUpdated"] = "identifyOnSessionSignatureUpdated";
|
|
118
104
|
})(IdentifyAction || (IdentifyAction = {}));
|
|
119
105
|
|
|
120
106
|
/**
|
|
@@ -141,13 +127,12 @@ class Identify extends Emitter {
|
|
|
141
127
|
super();
|
|
142
128
|
this.sdk = sdk;
|
|
143
129
|
this.wasLoggedIn = false;
|
|
144
|
-
this._credentials = null;
|
|
145
130
|
this._signature = null;
|
|
146
131
|
this._userData = null;
|
|
147
132
|
this._state = {
|
|
148
133
|
state: 'logged_out',
|
|
149
134
|
};
|
|
150
|
-
this._options = Object.assign({ strategy: 'email',
|
|
135
|
+
this._options = Object.assign({ strategy: 'email', version: 1 }, options);
|
|
151
136
|
}
|
|
152
137
|
static async fetchIdentifyHost(host, projectId) {
|
|
153
138
|
var _a, _b;
|
|
@@ -170,12 +155,13 @@ class Identify extends Emitter {
|
|
|
170
155
|
case 'logged_in':
|
|
171
156
|
this.wasLoggedIn = true;
|
|
172
157
|
break;
|
|
173
|
-
case 'logged_out':
|
|
174
158
|
case 'error':
|
|
175
159
|
this.wasLoggedIn = false;
|
|
176
160
|
break;
|
|
161
|
+
case 'logged_out':
|
|
177
162
|
case 'pending':
|
|
178
|
-
// preserve wasLoggedIn
|
|
163
|
+
// preserve wasLoggedIn — these states reflect transient transport
|
|
164
|
+
// state, not a deliberate logout (credentials are the gate for that)
|
|
179
165
|
break;
|
|
180
166
|
default: {
|
|
181
167
|
// Exhaustiveness check: TypeScript errors if a new state is added
|
|
@@ -203,53 +189,29 @@ class Identify extends Emitter {
|
|
|
203
189
|
this.signature = null;
|
|
204
190
|
}, SIGNATURE_TTL);
|
|
205
191
|
}
|
|
206
|
-
this.emit(IdentifyEvent.SignatureUpdated, this.signature);
|
|
207
192
|
}
|
|
208
193
|
get signature() {
|
|
209
194
|
return this._signature;
|
|
210
195
|
}
|
|
211
|
-
set credentials(credentials) {
|
|
212
|
-
if (this._credentials === credentials) {
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
this._credentials = credentials;
|
|
216
|
-
this.emit(IdentifyEvent.CredentialsUpdated, credentials);
|
|
217
|
-
}
|
|
218
|
-
get credentials() {
|
|
219
|
-
return this._credentials;
|
|
220
|
-
}
|
|
221
196
|
set userData(data) {
|
|
222
197
|
if (this._userData === data) {
|
|
223
198
|
return;
|
|
224
199
|
}
|
|
225
200
|
this._userData = data;
|
|
226
|
-
clearTimeout(this.userDataExpireTimeout);
|
|
227
|
-
this.emit(IdentifyEvent.UserdataUpdated, data);
|
|
228
201
|
}
|
|
229
202
|
get userData() {
|
|
230
203
|
return this._userData;
|
|
231
204
|
}
|
|
232
|
-
get shouldLoginOnReconnect() {
|
|
233
|
-
return (this.wasLoggedIn &&
|
|
234
|
-
this.options.loginPolicy === 'auto' &&
|
|
235
|
-
this.credentials !== null);
|
|
236
|
-
}
|
|
237
|
-
reset() {
|
|
238
|
-
this.credentials = null;
|
|
239
|
-
this.userData = null;
|
|
240
|
-
this.signature = null;
|
|
241
|
-
this.wasLoggedIn = false;
|
|
242
|
-
}
|
|
243
205
|
async getUrl(path = '') {
|
|
244
|
-
const {
|
|
206
|
+
const { host, projectId } = this.sdk.options;
|
|
245
207
|
if (this.host === undefined) {
|
|
246
208
|
this.host = await Identify.fetchIdentifyHost(host, projectId);
|
|
247
209
|
}
|
|
248
210
|
const url = new URL(this.host);
|
|
249
|
-
const { version,
|
|
211
|
+
const { version, strategy, provider } = this._options;
|
|
250
212
|
url.pathname = `/v${version}${path}`;
|
|
251
213
|
url.searchParams.set('projectId', projectId);
|
|
252
|
-
url.searchParams.set('deviceId',
|
|
214
|
+
url.searchParams.set('deviceId', getDeviceId());
|
|
253
215
|
url.searchParams.set('strategy', strategy);
|
|
254
216
|
if (provider !== undefined) {
|
|
255
217
|
url.searchParams.set('provider', provider);
|
|
@@ -284,6 +246,101 @@ function deleteExperience(experience) {
|
|
|
284
246
|
}
|
|
285
247
|
}
|
|
286
248
|
|
|
249
|
+
/**
|
|
250
|
+
* @license
|
|
251
|
+
* @monterosa/sdk-identify-kit
|
|
252
|
+
*
|
|
253
|
+
* Copyright © 2026 Monterosa Productions Limited. All rights reserved.
|
|
254
|
+
*
|
|
255
|
+
* More details on the license can be found at https://www.monterosa.co/sdk/license
|
|
256
|
+
*/
|
|
257
|
+
/**
|
|
258
|
+
* Locally-owned login policy.
|
|
259
|
+
*
|
|
260
|
+
* Defaults to `'disabled'`. Set via the public `setLoginPolicy`. Never
|
|
261
|
+
* propagated across the wire — each level owns its own policy.
|
|
262
|
+
*
|
|
263
|
+
* @internal
|
|
264
|
+
*/
|
|
265
|
+
class LoginPolicyStore extends Emitter {
|
|
266
|
+
constructor() {
|
|
267
|
+
super();
|
|
268
|
+
this._policy = 'disabled';
|
|
269
|
+
}
|
|
270
|
+
static getInstance() {
|
|
271
|
+
if (!LoginPolicyStore.instance) {
|
|
272
|
+
LoginPolicyStore.instance = new LoginPolicyStore();
|
|
273
|
+
}
|
|
274
|
+
return LoginPolicyStore.instance;
|
|
275
|
+
}
|
|
276
|
+
get policy() {
|
|
277
|
+
return this._policy;
|
|
278
|
+
}
|
|
279
|
+
set policy(next) {
|
|
280
|
+
if (this._policy === next) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
this._policy = next;
|
|
284
|
+
this.emit(IdentifyEvent.LoginPolicyUpdated, next);
|
|
285
|
+
}
|
|
286
|
+
subscribe(handler) {
|
|
287
|
+
return subscribe(this, IdentifyEvent.LoginPolicyUpdated, handler);
|
|
288
|
+
}
|
|
289
|
+
reset() {
|
|
290
|
+
this._policy = 'disabled';
|
|
291
|
+
this.off(IdentifyEvent.LoginPolicyUpdated);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* @license
|
|
297
|
+
* @monterosa/sdk-identify-kit
|
|
298
|
+
*
|
|
299
|
+
* Copyright © 2026 Monterosa Productions Limited. All rights reserved.
|
|
300
|
+
*
|
|
301
|
+
* More details on the license can be found at https://www.monterosa.co/sdk/license
|
|
302
|
+
*/
|
|
303
|
+
/**
|
|
304
|
+
* Root-owned credentials slot.
|
|
305
|
+
*
|
|
306
|
+
* Single source of truth at the root of an integration; an internal
|
|
307
|
+
* mirror at every other level, kept in sync via `Login` / `Logout`
|
|
308
|
+
* broadcasts. Not exposed publicly — public access flows through
|
|
309
|
+
* `setCredentials` / `getCredentials` / `clearCredentials` and
|
|
310
|
+
* `onCredentialsUpdated`.
|
|
311
|
+
*
|
|
312
|
+
* @internal
|
|
313
|
+
*/
|
|
314
|
+
class CredentialsStore extends Emitter {
|
|
315
|
+
constructor() {
|
|
316
|
+
super();
|
|
317
|
+
this._credentials = null;
|
|
318
|
+
}
|
|
319
|
+
static getInstance() {
|
|
320
|
+
if (!CredentialsStore.instance) {
|
|
321
|
+
CredentialsStore.instance = new CredentialsStore();
|
|
322
|
+
}
|
|
323
|
+
return CredentialsStore.instance;
|
|
324
|
+
}
|
|
325
|
+
get credentials() {
|
|
326
|
+
return this._credentials;
|
|
327
|
+
}
|
|
328
|
+
set credentials(next) {
|
|
329
|
+
if (this._credentials === next) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
this._credentials = next;
|
|
333
|
+
this.emit(IdentifyEvent.CredentialsUpdated, next);
|
|
334
|
+
}
|
|
335
|
+
subscribe(handler) {
|
|
336
|
+
return subscribe(this, IdentifyEvent.CredentialsUpdated, handler);
|
|
337
|
+
}
|
|
338
|
+
reset() {
|
|
339
|
+
this._credentials = null;
|
|
340
|
+
this.off(IdentifyEvent.CredentialsUpdated);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
287
344
|
/**
|
|
288
345
|
* @license
|
|
289
346
|
* identify-kit
|
|
@@ -292,8 +349,87 @@ function deleteExperience(experience) {
|
|
|
292
349
|
*
|
|
293
350
|
* More details on the license can be found at https://www.monterosa.co/sdk/license
|
|
294
351
|
*/
|
|
352
|
+
const loginPolicyStore = LoginPolicyStore.getInstance();
|
|
353
|
+
const credentialsStore = CredentialsStore.getInstance();
|
|
354
|
+
/**
|
|
355
|
+
* @internal
|
|
356
|
+
*/
|
|
295
357
|
const identifyKits = new Map();
|
|
296
|
-
|
|
358
|
+
/**
|
|
359
|
+
* Emitter for identify request events that are not tied to a specific
|
|
360
|
+
* identify instance (login / logout requests).
|
|
361
|
+
*
|
|
362
|
+
* @internal
|
|
363
|
+
*/
|
|
364
|
+
const requestsEmitter = new Emitter();
|
|
365
|
+
/**
|
|
366
|
+
* Read the current locally-owned login policy.
|
|
367
|
+
*
|
|
368
|
+
* Returns `'disabled'` by default.
|
|
369
|
+
*
|
|
370
|
+
* @internal
|
|
371
|
+
*/
|
|
372
|
+
function getLoginPolicy() {
|
|
373
|
+
return loginPolicyStore.policy;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Set the locally-owned login policy.
|
|
377
|
+
*
|
|
378
|
+
* All `Identify` instances at this level honour the same policy; the
|
|
379
|
+
* value is never propagated across the wire (each level of a multi-level
|
|
380
|
+
* integration owns its own policy).
|
|
381
|
+
*
|
|
382
|
+
* Policy gates the Enmasse `loginTask` only — credentials always mirror
|
|
383
|
+
* from upstream regardless of policy. A `'disabled'` level still
|
|
384
|
+
* receives credentials via the module-load pull and the cascading
|
|
385
|
+
* `Login` / `Logout` broadcasts; it just doesn't attempt Enmasse
|
|
386
|
+
* validation against them.
|
|
387
|
+
*
|
|
388
|
+
* When the policy transitions to `'auto'`, enqueues a sync-state task
|
|
389
|
+
* for every existing identify so that any in-flight session is picked
|
|
390
|
+
* up.
|
|
391
|
+
*
|
|
392
|
+
* Idempotent: setting the same policy that's already in effect is a
|
|
393
|
+
* no-op.
|
|
394
|
+
*
|
|
395
|
+
* @param policy - `'auto'` to enable auto-login, `'disabled'` to opt out.
|
|
396
|
+
*/
|
|
397
|
+
function setLoginPolicy(policy) {
|
|
398
|
+
if (loginPolicyStore.policy === policy) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
loginPolicyStore.policy = policy;
|
|
402
|
+
if (policy !== 'auto') {
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
// On transition to 'auto': if the local credentials slot already
|
|
406
|
+
// has a value (typical after the non-root module-load pull, or after
|
|
407
|
+
// a setCredentials at the root, or after an upstream Login broadcast
|
|
408
|
+
// has cascaded down), enqueue a login task for each existing
|
|
409
|
+
// identify. If the slot is empty, do nothing — a future credentials
|
|
410
|
+
// arrival via `applyLogin` will trigger the login under this new
|
|
411
|
+
// policy.
|
|
412
|
+
const { credentials } = credentialsStore;
|
|
413
|
+
if (credentials === null) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
for (const identify of identifyKits.values()) {
|
|
417
|
+
enqueueLogin(identify, credentials);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Whether the user should be auto-logged in on reconnect.
|
|
422
|
+
*
|
|
423
|
+
* True when the user was previously logged in, the policy is `'auto'`,
|
|
424
|
+
* and credentials are available on the identify instance.
|
|
425
|
+
*
|
|
426
|
+
* @internal
|
|
427
|
+
*/
|
|
428
|
+
function shouldLoginOnReconnect(identify) {
|
|
429
|
+
return (identify.wasLoggedIn &&
|
|
430
|
+
getLoginPolicy() === 'auto' &&
|
|
431
|
+
credentialsStore.credentials !== null);
|
|
432
|
+
}
|
|
297
433
|
/**
|
|
298
434
|
* @internal
|
|
299
435
|
*/
|
|
@@ -330,17 +466,13 @@ async function api(url, token, method = 'GET') {
|
|
|
330
466
|
/**
|
|
331
467
|
* @internal
|
|
332
468
|
*/
|
|
333
|
-
async function
|
|
334
|
-
var _a;
|
|
469
|
+
async function sendParentRequest(action, payload) {
|
|
335
470
|
const parentApp = getParentApplication();
|
|
336
471
|
if (parentApp === null) {
|
|
337
472
|
throw createError(IdentifyError.NoParentApplication, IdentifyErrorMessages);
|
|
338
473
|
}
|
|
339
|
-
const { host, projectId } = identify.sdk.options;
|
|
340
|
-
// Preserve existing origin (relay) or set from current context (source)
|
|
341
|
-
const origin = (_a = payload === null || payload === void 0 ? void 0 : payload.origin) !== null && _a !== void 0 ? _a : { host, projectId };
|
|
342
474
|
try {
|
|
343
|
-
const response = await sendSdkRequest(parentApp, action,
|
|
475
|
+
const response = await sendSdkRequest(parentApp, action, payload);
|
|
344
476
|
const { error, data } = response.payload;
|
|
345
477
|
if (error !== undefined) {
|
|
346
478
|
throw createError(IdentifyError.ParentAppError, IdentifyErrorMessages, error);
|
|
@@ -356,12 +488,6 @@ async function parentAppRequest(identify, action, payload) {
|
|
|
356
488
|
throw err;
|
|
357
489
|
}
|
|
358
490
|
}
|
|
359
|
-
/**
|
|
360
|
-
* @internal
|
|
361
|
-
*/
|
|
362
|
-
function registerIdentifyHook(hook) {
|
|
363
|
-
identifyHooks.push(hook);
|
|
364
|
-
}
|
|
365
491
|
/**
|
|
366
492
|
* @internal
|
|
367
493
|
*/
|
|
@@ -385,6 +511,9 @@ const logoutWithRetry = withRetryAsync(logout);
|
|
|
385
511
|
* @internal
|
|
386
512
|
*/
|
|
387
513
|
async function loginTask(identify, credentials) {
|
|
514
|
+
if (identify.state.state === 'logged_in') {
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
388
517
|
try {
|
|
389
518
|
identify.state = {
|
|
390
519
|
state: 'pending',
|
|
@@ -398,6 +527,11 @@ async function loginTask(identify, credentials) {
|
|
|
398
527
|
}
|
|
399
528
|
}
|
|
400
529
|
catch (err) {
|
|
530
|
+
// Abandon any pending login/logout/sync tasks on failure — letting
|
|
531
|
+
// them run after an error would put the user in an inconsistent
|
|
532
|
+
// state. Note: this also drops tasks for unrelated identifies that
|
|
533
|
+
// share the queue; acceptable because the typical runtime has one
|
|
534
|
+
// identify per project.
|
|
401
535
|
taskQueue.clear();
|
|
402
536
|
identify.state = {
|
|
403
537
|
state: 'error',
|
|
@@ -410,6 +544,9 @@ async function loginTask(identify, credentials) {
|
|
|
410
544
|
* @internal
|
|
411
545
|
*/
|
|
412
546
|
async function logoutTask(identify) {
|
|
547
|
+
if (identify.state.state === 'logged_out') {
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
413
550
|
try {
|
|
414
551
|
identify.state = {
|
|
415
552
|
state: 'pending',
|
|
@@ -423,6 +560,8 @@ async function logoutTask(identify) {
|
|
|
423
560
|
}
|
|
424
561
|
}
|
|
425
562
|
catch (err) {
|
|
563
|
+
// Abandon any pending login/logout/sync tasks on failure — see
|
|
564
|
+
// `loginTask` for the rationale.
|
|
426
565
|
taskQueue.clear();
|
|
427
566
|
identify.state = {
|
|
428
567
|
state: 'error',
|
|
@@ -432,15 +571,53 @@ async function logoutTask(identify) {
|
|
|
432
571
|
}
|
|
433
572
|
}
|
|
434
573
|
/**
|
|
574
|
+
* Enqueue a `loginTask` for the given identify when `policy === 'auto'`.
|
|
575
|
+
* The downstream `Login` broadcast is emitted by {@link applyLogin}.
|
|
576
|
+
*
|
|
435
577
|
* @internal
|
|
436
578
|
*/
|
|
437
579
|
function enqueueLogin(identify, credentials, prioritise = false) {
|
|
438
|
-
if (
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
580
|
+
if (getLoginPolicy() !== 'auto') {
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
if (prioritise) {
|
|
584
|
+
taskQueue.enqueueFront(() => loginTask(identify, credentials));
|
|
585
|
+
}
|
|
586
|
+
else {
|
|
587
|
+
taskQueue.enqueue(() => loginTask(identify, credentials));
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Reset the identify's identity-derived caches and enqueue a `logoutTask`
|
|
592
|
+
* when `policy === 'auto'`.
|
|
593
|
+
*
|
|
594
|
+
* @internal
|
|
595
|
+
*/
|
|
596
|
+
function enqueueLogout(identify) {
|
|
597
|
+
identify.userData = null;
|
|
598
|
+
identify.signature = null;
|
|
599
|
+
if (getLoginPolicy() !== 'auto') {
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
taskQueue.enqueue(() => logoutTask(identify));
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Apply new credentials at this level: update the slot, enqueue a
|
|
606
|
+
* `loginTask` for every existing identify on the null-to-set transition,
|
|
607
|
+
* and broadcast `Login` downstream to every embedded experience.
|
|
608
|
+
*
|
|
609
|
+
* Idempotent on token refresh: re-setting an already-set slot updates
|
|
610
|
+
* the value and broadcasts, but does not re-enqueue logins (their
|
|
611
|
+
* `loginTask` would short-circuit on `state === 'logged_in'` anyway).
|
|
612
|
+
*
|
|
613
|
+
* @internal
|
|
614
|
+
*/
|
|
615
|
+
function applyLogin(credentials) {
|
|
616
|
+
const shouldLogin = credentialsStore.credentials === null;
|
|
617
|
+
credentialsStore.credentials = credentials;
|
|
618
|
+
if (shouldLogin) {
|
|
619
|
+
for (const identify of identifyKits.values()) {
|
|
620
|
+
enqueueLogin(identify, credentials);
|
|
444
621
|
}
|
|
445
622
|
}
|
|
446
623
|
for (const experience of getExperiences()) {
|
|
@@ -448,14 +625,50 @@ function enqueueLogin(identify, credentials, prioritise = false) {
|
|
|
448
625
|
}
|
|
449
626
|
}
|
|
450
627
|
/**
|
|
628
|
+
* Clear credentials at this level: null out the slot, enqueue a
|
|
629
|
+
* `logoutTask` for every existing identify on the set-to-null
|
|
630
|
+
* transition, and broadcast `Logout` downstream to every embedded
|
|
631
|
+
* experience.
|
|
632
|
+
*
|
|
451
633
|
* @internal
|
|
452
634
|
*/
|
|
453
|
-
function
|
|
454
|
-
|
|
455
|
-
|
|
635
|
+
function applyLogout() {
|
|
636
|
+
const shouldLogout = credentialsStore.credentials !== null;
|
|
637
|
+
credentialsStore.credentials = null;
|
|
638
|
+
if (shouldLogout) {
|
|
639
|
+
for (const identify of identifyKits.values()) {
|
|
640
|
+
enqueueLogout(identify);
|
|
641
|
+
}
|
|
456
642
|
}
|
|
457
643
|
for (const experience of getExperiences()) {
|
|
458
|
-
sendSdkMessage(experience, IdentifyAction.Logout);
|
|
644
|
+
sendSdkMessage(experience, IdentifyAction.Logout, {});
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Pull state from the parent application and apply locally.
|
|
649
|
+
*
|
|
650
|
+
* Fires once at non-root bridge module load, regardless of
|
|
651
|
+
* `loginPolicy` — token presence is the customer-side sign-in state and
|
|
652
|
+
* must mirror upstream whether or not we choose to validate against
|
|
653
|
+
* Enmasse. Best-effort: a missing or non-identify-kit parent silently
|
|
654
|
+
* resolves with no slot change.
|
|
655
|
+
*
|
|
656
|
+
* Uses {@link applyLogin} so the slot update cascades downstream to
|
|
657
|
+
* this level's own embedded experiences and per-identify loginTasks
|
|
658
|
+
* are enqueued under `loginPolicy === 'auto'`.
|
|
659
|
+
*
|
|
660
|
+
* @internal
|
|
661
|
+
*/
|
|
662
|
+
async function pullStateFromParent() {
|
|
663
|
+
let credentials;
|
|
664
|
+
try {
|
|
665
|
+
credentials = await getCredentials();
|
|
666
|
+
}
|
|
667
|
+
catch (_a) {
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
if (credentials !== null) {
|
|
671
|
+
applyLogin(credentials);
|
|
459
672
|
}
|
|
460
673
|
}
|
|
461
674
|
function getIdentify(sdkOrOptions, options) {
|
|
@@ -487,36 +700,31 @@ function getIdentify(sdkOrOptions, options) {
|
|
|
487
700
|
sdk = getSdk();
|
|
488
701
|
identifyOptions = {};
|
|
489
702
|
}
|
|
490
|
-
const {
|
|
703
|
+
const { projectId } = sdk.options;
|
|
491
704
|
if (identifyKits.has(projectId)) {
|
|
492
705
|
return identifyKits.get(projectId);
|
|
493
706
|
}
|
|
494
707
|
const identify = new Identify(sdk, identifyOptions);
|
|
495
|
-
for (const hook of identifyHooks) {
|
|
496
|
-
hook(identify);
|
|
497
|
-
}
|
|
498
708
|
watchConnectionStatus(identify);
|
|
499
709
|
identifyKits.set(projectId, identify);
|
|
500
710
|
return identify;
|
|
501
711
|
}
|
|
502
712
|
/**
|
|
503
|
-
*
|
|
713
|
+
* Requests a user login.
|
|
504
714
|
*
|
|
505
715
|
* @example
|
|
506
716
|
* ```javascript
|
|
507
717
|
* import { configure } from '@monterosa/sdk-core';
|
|
508
|
-
* import {
|
|
718
|
+
* import { requestLogin } from '@monterosa/sdk-identify-kit';
|
|
509
719
|
*
|
|
510
720
|
* configure({ host: '...', projectId: '...' });
|
|
511
721
|
*
|
|
512
722
|
* try {
|
|
513
|
-
*
|
|
514
|
-
*
|
|
515
|
-
* await requestLogin(identify);
|
|
723
|
+
* await requestLogin();
|
|
516
724
|
*
|
|
517
725
|
* console.log('Login request successful');
|
|
518
726
|
* } catch (err) {
|
|
519
|
-
* console.error('Error requesting login:',
|
|
727
|
+
* console.error('Error requesting login:', err.message)
|
|
520
728
|
* }
|
|
521
729
|
* ```
|
|
522
730
|
*
|
|
@@ -525,56 +733,67 @@ function getIdentify(sdkOrOptions, options) {
|
|
|
525
733
|
* the Monterosa SDK, the function delegates to the parent app
|
|
526
734
|
* to handle the login process.
|
|
527
735
|
*
|
|
528
|
-
* @param identify - An instance of the `IdentifyKit` class used for user
|
|
529
|
-
* identification.
|
|
530
736
|
* @returns A Promise that resolves with `void` when the login request
|
|
531
737
|
* is completed.
|
|
532
738
|
*/
|
|
533
|
-
async function requestLogin(
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
await parentAppRequest(identify, IdentifyAction.RequestLogin);
|
|
739
|
+
async function requestLogin() {
|
|
740
|
+
if (getParentApplication() !== null) {
|
|
741
|
+
await sendParentRequest(IdentifyAction.RequestLogin);
|
|
537
742
|
return;
|
|
538
743
|
}
|
|
539
|
-
|
|
744
|
+
requestsEmitter.emit(IdentifyEvent.LoginRequested);
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Read the current credentials, pulling from the parent application when
|
|
748
|
+
* called from an embedded experience.
|
|
749
|
+
*
|
|
750
|
+
* At the root this returns the canonical slot value. At a non-root
|
|
751
|
+
* experience this dispatches a `GetCredentials` request upstream and
|
|
752
|
+
* resolves with the response, ensuring the caller always sees the
|
|
753
|
+
* authoritative value rather than a possibly-stale local mirror.
|
|
754
|
+
*
|
|
755
|
+
* @returns A Promise that resolves to the current credentials, or `null`
|
|
756
|
+
* if none are set.
|
|
757
|
+
*/
|
|
758
|
+
async function getCredentials() {
|
|
759
|
+
if (getParentApplication() === null) {
|
|
760
|
+
return credentialsStore.credentials;
|
|
761
|
+
}
|
|
762
|
+
return sendParentRequest(IdentifyAction.GetCredentials);
|
|
540
763
|
}
|
|
541
764
|
/**
|
|
542
|
-
*
|
|
765
|
+
* Requests a user logout.
|
|
543
766
|
*
|
|
544
767
|
* @example
|
|
545
768
|
* ```javascript
|
|
546
|
-
* import {
|
|
547
|
-
* import {
|
|
769
|
+
* import { configure } from '@monterosa/sdk-core';
|
|
770
|
+
* import { requestLogout } from '@monterosa/sdk-identify-kit';
|
|
548
771
|
*
|
|
549
|
-
*
|
|
550
|
-
* const identify = getIdentify(space);
|
|
772
|
+
* configure({ host: '...', projectId: '...' });
|
|
551
773
|
*
|
|
552
774
|
* try {
|
|
553
|
-
* await requestLogout(
|
|
775
|
+
* await requestLogout();
|
|
554
776
|
*
|
|
555
777
|
* console.log('Logout request successful');
|
|
556
778
|
* } catch (err) {
|
|
557
|
-
* console.error('Error requesting logout:',
|
|
779
|
+
* console.error('Error requesting logout:', err.message)
|
|
558
780
|
* }
|
|
559
781
|
* ```
|
|
560
782
|
*
|
|
561
783
|
* @remarks
|
|
562
784
|
* - If the app is running within a third-party application that uses
|
|
563
|
-
* the
|
|
785
|
+
* the Monterosa SDK, the function delegates to the parent app
|
|
564
786
|
* to handle the logout process.
|
|
565
787
|
*
|
|
566
|
-
* @param identify - An instance of the `IdentifyKit` class used for user
|
|
567
|
-
* identification.
|
|
568
788
|
* @returns A Promise that resolves with `void` when the logout request
|
|
569
789
|
* is completed.
|
|
570
790
|
*/
|
|
571
|
-
async function requestLogout(
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
await parentAppRequest(identify, IdentifyAction.RequestLogout);
|
|
791
|
+
async function requestLogout() {
|
|
792
|
+
if (getParentApplication() !== null) {
|
|
793
|
+
await sendParentRequest(IdentifyAction.RequestLogout);
|
|
575
794
|
return;
|
|
576
795
|
}
|
|
577
|
-
|
|
796
|
+
requestsEmitter.emit(IdentifyEvent.LogoutRequested);
|
|
578
797
|
}
|
|
579
798
|
/**
|
|
580
799
|
* @internal
|
|
@@ -593,11 +812,6 @@ async function requestLogout(identify) {
|
|
|
593
812
|
* @returns A Promise that resolves to a `Signature` object.
|
|
594
813
|
*/
|
|
595
814
|
async function getSessionSignature(identify, credentials) {
|
|
596
|
-
const parentApp = getParentApplication();
|
|
597
|
-
if (parentApp !== null) {
|
|
598
|
-
const signature = await parentAppRequest(identify, IdentifyAction.GetSessionSignature, credentials);
|
|
599
|
-
return signature;
|
|
600
|
-
}
|
|
601
815
|
if (identify.signature !== null) {
|
|
602
816
|
return identify.signature;
|
|
603
817
|
}
|
|
@@ -608,59 +822,60 @@ async function getSessionSignature(identify, credentials) {
|
|
|
608
822
|
return signature;
|
|
609
823
|
}
|
|
610
824
|
/**
|
|
611
|
-
* A memoized version of the `getSessionSignature` function.
|
|
825
|
+
* A memoized version of the `getSessionSignature` function. Memo key is
|
|
826
|
+
* the credentials token, so both leaf-side and bridge-side callers share
|
|
827
|
+
* the same cache for the same token.
|
|
612
828
|
*/
|
|
613
829
|
const getSessionSignatureMemoized = memoizePromise(getSessionSignature, (identify, credentials) => credentials.token, {
|
|
614
830
|
clearOnResolve: true,
|
|
615
831
|
clearOnReject: true,
|
|
616
832
|
});
|
|
617
833
|
/**
|
|
618
|
-
*
|
|
619
|
-
*
|
|
834
|
+
* Fetches user data for the given credentials.
|
|
835
|
+
*
|
|
836
|
+
* Credentials are required explicitly so the precondition is visible at
|
|
837
|
+
* the call site — without them the function cannot be called. Obtain a
|
|
838
|
+
* `Credentials` value via {@link getCredentials} or the
|
|
839
|
+
* {@link onCredentialsUpdated} callback.
|
|
620
840
|
*
|
|
621
841
|
* @example
|
|
622
842
|
* ```javascript
|
|
623
843
|
* import { configure } from '@monterosa/sdk-core';
|
|
624
|
-
* import {
|
|
844
|
+
* import {
|
|
845
|
+
* getIdentify,
|
|
846
|
+
* getUserData,
|
|
847
|
+
* getCredentials,
|
|
848
|
+
* } from '@monterosa/sdk-identify-kit';
|
|
625
849
|
*
|
|
626
850
|
* configure({ host: '...', projectId: '...' });
|
|
627
851
|
*
|
|
628
852
|
* const identify = getIdentify();
|
|
629
|
-
* const
|
|
853
|
+
* const credentials = await getCredentials();
|
|
630
854
|
*
|
|
631
|
-
*
|
|
855
|
+
* if (credentials !== null) {
|
|
856
|
+
* const userData = await getUserData(identify, credentials);
|
|
857
|
+
* console.log('User data:', userData);
|
|
858
|
+
* }
|
|
632
859
|
* ```
|
|
633
860
|
*
|
|
634
861
|
* @remarks
|
|
635
|
-
*
|
|
636
|
-
*
|
|
637
|
-
* to get user data.
|
|
638
|
-
*
|
|
639
|
-
* - If the request is successful, the function resolves with a key-value object
|
|
640
|
-
* representing user data. If not, a `MonterosaError` is thrown.
|
|
862
|
+
* Cached on the identify instance after the first successful fetch.
|
|
863
|
+
* Cleared on {@link clearCredentials} via the logout path.
|
|
641
864
|
*
|
|
642
865
|
* @param identify - An instance of `IdentifyKit` that provides the user
|
|
643
866
|
* identification functionality.
|
|
644
|
-
* @
|
|
645
|
-
*
|
|
646
|
-
*
|
|
647
|
-
*
|
|
867
|
+
* @param credentials - The user's authentication credentials. The
|
|
868
|
+
* request authorises against the value's token.
|
|
869
|
+
* @returns A Promise that resolves to a key-value object representing
|
|
870
|
+
* user data. The structure and content of the user data object depend
|
|
871
|
+
* on the identify service provider and may vary.
|
|
648
872
|
*/
|
|
649
|
-
async function getUserData(identify) {
|
|
650
|
-
const parentApp = getParentApplication();
|
|
651
|
-
if (parentApp !== null) {
|
|
652
|
-
const userData = await parentAppRequest(identify, IdentifyAction.GetUserData);
|
|
653
|
-
return userData;
|
|
654
|
-
}
|
|
655
|
-
// Return cached user data if available
|
|
873
|
+
async function getUserData(identify, credentials) {
|
|
656
874
|
if (identify.userData !== null) {
|
|
657
875
|
return identify.userData;
|
|
658
876
|
}
|
|
659
|
-
if (identify.credentials === null) {
|
|
660
|
-
throw createError(IdentifyError.NoCredentials, IdentifyErrorMessages);
|
|
661
|
-
}
|
|
662
877
|
const url = await identify.getUrl('/user');
|
|
663
|
-
const { data } = await api(url,
|
|
878
|
+
const { data } = await api(url, credentials.token);
|
|
664
879
|
identify.userData = data;
|
|
665
880
|
return data;
|
|
666
881
|
}
|
|
@@ -670,41 +885,32 @@ async function getUserData(identify) {
|
|
|
670
885
|
* @example
|
|
671
886
|
* ```javascript
|
|
672
887
|
* import { configure } from '@monterosa/sdk-core';
|
|
673
|
-
* import {
|
|
888
|
+
* import { setCredentials } from '@monterosa/sdk-identify-kit';
|
|
674
889
|
*
|
|
675
890
|
* configure({ host: '...', projectId: '...' });
|
|
676
891
|
*
|
|
677
|
-
*
|
|
678
|
-
* const identify = getIdentify();
|
|
679
|
-
*
|
|
680
|
-
* await setCredentials(identify, credentials)
|
|
892
|
+
* await setCredentials({ token: 'abc123' });
|
|
681
893
|
* ```
|
|
682
894
|
*
|
|
683
895
|
* @remarks
|
|
684
|
-
* -
|
|
685
|
-
*
|
|
686
|
-
*
|
|
687
|
-
*
|
|
688
|
-
*
|
|
689
|
-
*
|
|
896
|
+
* - At the root of an integration, the credentials are stored locally
|
|
897
|
+
* and a `Login` broadcast is sent to every embedded experience.
|
|
898
|
+
* - When called from an embedded experience, the call is relayed
|
|
899
|
+
* upstream via the `SetCredentials` wire action. The credentials are
|
|
900
|
+
* ultimately applied at the root and propagate back down via the
|
|
901
|
+
* cascading `Login` broadcast.
|
|
690
902
|
*
|
|
691
|
-
* @param identify - An instance of `IdentifyKit` that provides the user
|
|
692
|
-
* identification functionality.
|
|
693
903
|
* @param credentials - An object representing the user's authentication
|
|
694
904
|
* credentials.
|
|
695
|
-
* @returns A Promise that resolves to `void
|
|
905
|
+
* @returns A Promise that resolves to `void` once the credentials have
|
|
906
|
+
* been written (root) or the upstream relay has completed (non-root).
|
|
696
907
|
*/
|
|
697
|
-
async function setCredentials(
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
await parentAppRequest(identify, IdentifyAction.SetCredentials, credentials);
|
|
908
|
+
async function setCredentials(credentials) {
|
|
909
|
+
if (getParentApplication() !== null) {
|
|
910
|
+
await sendParentRequest(IdentifyAction.SetCredentials, credentials);
|
|
701
911
|
return;
|
|
702
912
|
}
|
|
703
|
-
|
|
704
|
-
identify.credentials = credentials;
|
|
705
|
-
if (shouldLogin) {
|
|
706
|
-
enqueueLogin(identify, credentials);
|
|
707
|
-
}
|
|
913
|
+
applyLogin(credentials);
|
|
708
914
|
}
|
|
709
915
|
/**
|
|
710
916
|
* Clears the user's authentication credentials.
|
|
@@ -712,40 +918,30 @@ async function setCredentials(identify, credentials) {
|
|
|
712
918
|
* @example
|
|
713
919
|
* ```javascript
|
|
714
920
|
* import { configure } from '@monterosa/sdk-core';
|
|
715
|
-
* import {
|
|
921
|
+
* import { clearCredentials } from '@monterosa/sdk-identify-kit';
|
|
716
922
|
*
|
|
717
923
|
* configure({ host: '...', projectId: '...' });
|
|
718
924
|
*
|
|
719
|
-
*
|
|
720
|
-
*
|
|
721
|
-
* await clearCredentials(identify);
|
|
925
|
+
* await clearCredentials();
|
|
722
926
|
* ```
|
|
723
927
|
*
|
|
724
928
|
* @remarks
|
|
725
|
-
* -
|
|
726
|
-
*
|
|
727
|
-
*
|
|
728
|
-
*
|
|
729
|
-
*
|
|
730
|
-
*
|
|
731
|
-
*
|
|
732
|
-
* @
|
|
733
|
-
*
|
|
734
|
-
* @returns A Promise that resolves to `void`.
|
|
929
|
+
* - At the root of an integration, the credentials slot is cleared and
|
|
930
|
+
* a `Logout` broadcast is sent to every embedded experience.
|
|
931
|
+
* - When called from an embedded experience, the call is relayed
|
|
932
|
+
* upstream via the `ClearCredentials` wire action. The slot is
|
|
933
|
+
* cleared at the root and the cascading `Logout` broadcast propagates
|
|
934
|
+
* back down.
|
|
935
|
+
*
|
|
936
|
+
* @returns A Promise that resolves to `void` once the slot has been
|
|
937
|
+
* cleared (root) or the upstream relay has completed (non-root).
|
|
735
938
|
*/
|
|
736
|
-
async function clearCredentials(
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
await parentAppRequest(identify, IdentifyAction.ClearCredentials);
|
|
939
|
+
async function clearCredentials() {
|
|
940
|
+
if (getParentApplication() !== null) {
|
|
941
|
+
await sendParentRequest(IdentifyAction.ClearCredentials);
|
|
740
942
|
return;
|
|
741
943
|
}
|
|
742
|
-
|
|
743
|
-
identify.credentials = null;
|
|
744
|
-
identify.userData = null;
|
|
745
|
-
identify.signature = null;
|
|
746
|
-
if (shouldLogout) {
|
|
747
|
-
enqueueLogout(identify);
|
|
748
|
-
}
|
|
944
|
+
applyLogout();
|
|
749
945
|
}
|
|
750
946
|
/**
|
|
751
947
|
* Registers a callback function that will be called whenever the `LoginState`
|
|
@@ -779,19 +975,17 @@ function onStateUpdated(identify, callback) {
|
|
|
779
975
|
return subscribe(identify, IdentifyEvent.StateUpdated, callback);
|
|
780
976
|
}
|
|
781
977
|
/**
|
|
782
|
-
* Registers a callback function that will be called whenever the
|
|
783
|
-
*
|
|
978
|
+
* Registers a callback function that will be called whenever the
|
|
979
|
+
* credentials slot is updated.
|
|
784
980
|
*
|
|
785
981
|
* @example
|
|
786
982
|
* ```javascript
|
|
787
983
|
* import { configure } from '@monterosa/sdk-core';
|
|
788
|
-
* import {
|
|
984
|
+
* import { onCredentialsUpdated } from '@monterosa/sdk-identify-kit';
|
|
789
985
|
*
|
|
790
986
|
* configure({ host: '...', projectId: '...' });
|
|
791
987
|
*
|
|
792
|
-
* const
|
|
793
|
-
*
|
|
794
|
-
* const unsubscribe = onCredentialsUpdated(identify, (credentials) => {
|
|
988
|
+
* const unsubscribe = onCredentialsUpdated((credentials) => {
|
|
795
989
|
* if (credentials !== null) {
|
|
796
990
|
* console.log("Credentials updated:", credentials);
|
|
797
991
|
* } else {
|
|
@@ -803,91 +997,15 @@ function onStateUpdated(identify, callback) {
|
|
|
803
997
|
* // unsubscribe();
|
|
804
998
|
* ```
|
|
805
999
|
*
|
|
806
|
-
* @param identify - An instance of `IdentifyKit` that provides the user
|
|
807
|
-
* identification functionality.
|
|
808
1000
|
* @param callback - The callback function to register. This function will be
|
|
809
1001
|
* called with the updated `Credentials` object as its only argument.
|
|
810
|
-
* If the value `null` is received, it indicates that the
|
|
811
|
-
* been cleared
|
|
812
|
-
* @returns An `Unsubscribe` function that can be called to unregister
|
|
813
|
-
* the callback function.
|
|
814
|
-
*/
|
|
815
|
-
function onCredentialsUpdated(identify, callback) {
|
|
816
|
-
return subscribe(identify, IdentifyEvent.CredentialsUpdated, callback);
|
|
817
|
-
}
|
|
818
|
-
/**
|
|
819
|
-
* Registers a callback function that will be called whenever the `Signature`
|
|
820
|
-
* object associated with the `IdentifyKit` instance is updated.
|
|
821
|
-
*
|
|
822
|
-
* @example
|
|
823
|
-
* ```javascript
|
|
824
|
-
* import { configure } from '@monterosa/sdk-core';
|
|
825
|
-
* import { getIdentify, onSignatureUpdated } from '@monterosa/sdk-identify-kit';
|
|
826
|
-
*
|
|
827
|
-
* configure({ host: '...', projectId: '...' });
|
|
828
|
-
*
|
|
829
|
-
* const identify = getIdentify();
|
|
830
|
-
*
|
|
831
|
-
* const unsubscribe = onSignatureUpdated(identify, (signature) => {
|
|
832
|
-
* if (signature !== null) {
|
|
833
|
-
* console.log("Signature updated:", signature);
|
|
834
|
-
* } else {
|
|
835
|
-
* console.log("Signature cleared.");
|
|
836
|
-
* }
|
|
837
|
-
* });
|
|
838
|
-
*
|
|
839
|
-
* // Call unsubscribe() to unregister the callback function
|
|
840
|
-
* // unsubscribe();
|
|
841
|
-
* ```
|
|
842
|
-
*
|
|
843
|
-
* @param identify - An instance of `IdentifyKit` that provides the user
|
|
844
|
-
* identification functionality.
|
|
845
|
-
* @param callback - The callback function to register. This function will be
|
|
846
|
-
* called with the updated `Signature` object as its only argument.
|
|
847
|
-
* If the value `null` is received, it indicates that the signature has
|
|
848
|
-
* been cleared
|
|
1002
|
+
* If the value `null` is received, it indicates that the credentials have
|
|
1003
|
+
* been cleared.
|
|
849
1004
|
* @returns An `Unsubscribe` function that can be called to unregister
|
|
850
1005
|
* the callback function.
|
|
851
1006
|
*/
|
|
852
|
-
function
|
|
853
|
-
return subscribe(
|
|
854
|
-
}
|
|
855
|
-
/**
|
|
856
|
-
* Registers a callback function that will be called whenever the `UserData`
|
|
857
|
-
* object associated with the `IdentifyKit` instance is updated.
|
|
858
|
-
*
|
|
859
|
-
* @example
|
|
860
|
-
* ```javascript
|
|
861
|
-
* import { configure } from '@monterosa/sdk-core';
|
|
862
|
-
* import { getIdentify, onUserDataUpdated } from '@monterosa/sdk-identify-kit';
|
|
863
|
-
*
|
|
864
|
-
* configure({ host: '...', projectId: '...' });
|
|
865
|
-
*
|
|
866
|
-
* const identify = getIdentify();
|
|
867
|
-
*
|
|
868
|
-
* const unsubscribe = onUserDataUpdated(identify, (userData) => {
|
|
869
|
-
* if (userData !== null) {
|
|
870
|
-
* console.log("User's data updated:", userData);
|
|
871
|
-
* } else {
|
|
872
|
-
* console.log("User's data cleared.");
|
|
873
|
-
* }
|
|
874
|
-
* });
|
|
875
|
-
*
|
|
876
|
-
* // Call unsubscribe() to unregister the callback function
|
|
877
|
-
* // unsubscribe();
|
|
878
|
-
* ```
|
|
879
|
-
*
|
|
880
|
-
* @param identify - An instance of `IdentifyKit` that provides the user
|
|
881
|
-
* identification functionality.
|
|
882
|
-
* @param callback - The callback function to register. This function will be
|
|
883
|
-
* called with the updated `UserData` object as its only argument.
|
|
884
|
-
* If the value `null` is received, it indicates that the user's data has
|
|
885
|
-
* been cleared
|
|
886
|
-
* @returns An `Unsubscribe` function that can be called to unregister
|
|
887
|
-
* the callback function.
|
|
888
|
-
*/
|
|
889
|
-
function onUserDataUpdated(identify, callback) {
|
|
890
|
-
return subscribe(identify, IdentifyEvent.UserdataUpdated, callback);
|
|
1007
|
+
function onCredentialsUpdated(callback) {
|
|
1008
|
+
return credentialsStore.subscribe(callback);
|
|
891
1009
|
}
|
|
892
1010
|
/**
|
|
893
1011
|
* Registers a callback function that will be called when a login is requested
|
|
@@ -896,13 +1014,11 @@ function onUserDataUpdated(identify, callback) {
|
|
|
896
1014
|
* @example
|
|
897
1015
|
* ```javascript
|
|
898
1016
|
* import { configure } from '@monterosa/sdk-core';
|
|
899
|
-
* import {
|
|
1017
|
+
* import { onLoginRequestedByExperience } from '@monterosa/sdk-identify-kit';
|
|
900
1018
|
*
|
|
901
1019
|
* configure({ host: '...', projectId: '...' });
|
|
902
1020
|
*
|
|
903
|
-
* const
|
|
904
|
-
*
|
|
905
|
-
* const unsubscribe = onLoginRequestedByExperience(identify, () => {
|
|
1021
|
+
* const unsubscribe = onLoginRequestedByExperience(() => {
|
|
906
1022
|
* showLoginForm();
|
|
907
1023
|
* });
|
|
908
1024
|
*
|
|
@@ -910,15 +1026,13 @@ function onUserDataUpdated(identify, callback) {
|
|
|
910
1026
|
* // unsubscribe();
|
|
911
1027
|
* ```
|
|
912
1028
|
*
|
|
913
|
-
* @param identify - An instance of `IdentifyKit` that provides the user
|
|
914
|
-
* identification functionality.
|
|
915
1029
|
* @param callback - The callback function to register. This function will
|
|
916
1030
|
* be called when a login is requested by an Experience.
|
|
917
1031
|
* @returns An `Unsubscribe` function that can be called to unregister
|
|
918
1032
|
* the callback function.
|
|
919
1033
|
*/
|
|
920
|
-
function onLoginRequestedByExperience(
|
|
921
|
-
return subscribe(
|
|
1034
|
+
function onLoginRequestedByExperience(callback) {
|
|
1035
|
+
return subscribe(requestsEmitter, IdentifyEvent.LoginRequested, callback);
|
|
922
1036
|
}
|
|
923
1037
|
/**
|
|
924
1038
|
* Registers a callback function that will be called when a logout is requested
|
|
@@ -926,13 +1040,12 @@ function onLoginRequestedByExperience(identify, callback) {
|
|
|
926
1040
|
*
|
|
927
1041
|
* @example
|
|
928
1042
|
* ```javascript
|
|
929
|
-
* import {
|
|
930
|
-
* import {
|
|
1043
|
+
* import { configure } from '@monterosa/sdk-core';
|
|
1044
|
+
* import { onLogoutRequestedByExperience } from '@monterosa/sdk-identify-kit';
|
|
931
1045
|
*
|
|
932
|
-
*
|
|
933
|
-
* const identify = getIdentify(space);
|
|
1046
|
+
* configure({ host: '...', projectId: '...' });
|
|
934
1047
|
*
|
|
935
|
-
* const unsubscribe = onLogoutRequestedByExperience(
|
|
1048
|
+
* const unsubscribe = onLogoutRequestedByExperience(() => {
|
|
936
1049
|
* // logout requested by experience
|
|
937
1050
|
* // perform logout from Auth service
|
|
938
1051
|
* });
|
|
@@ -941,15 +1054,13 @@ function onLoginRequestedByExperience(identify, callback) {
|
|
|
941
1054
|
* // unsubscribe();
|
|
942
1055
|
* ```
|
|
943
1056
|
*
|
|
944
|
-
* @param identify - An instance of `IdentifyKit` that provides the user
|
|
945
|
-
* identification functionality.
|
|
946
1057
|
* @param callback - The callback function to register. This function will
|
|
947
1058
|
* be called when a logout is requested by an Experience.
|
|
948
1059
|
* @returns An `Unsubscribe` function that can be called to unregister
|
|
949
1060
|
* the callback function.
|
|
950
1061
|
*/
|
|
951
|
-
function onLogoutRequestedByExperience(
|
|
952
|
-
return subscribe(
|
|
1062
|
+
function onLogoutRequestedByExperience(callback) {
|
|
1063
|
+
return subscribe(requestsEmitter, IdentifyEvent.LogoutRequested, callback);
|
|
953
1064
|
}
|
|
954
1065
|
/**
|
|
955
1066
|
*
|
|
@@ -958,8 +1069,8 @@ function onLogoutRequestedByExperience(identify, callback) {
|
|
|
958
1069
|
async function watchConnectionStatus(identify) {
|
|
959
1070
|
const conn = await getConnect(identify.sdk.options.host);
|
|
960
1071
|
onConnected(conn, () => {
|
|
961
|
-
if (identify
|
|
962
|
-
enqueueLogin(identify,
|
|
1072
|
+
if (shouldLoginOnReconnect(identify)) {
|
|
1073
|
+
enqueueLogin(identify, credentialsStore.credentials, true);
|
|
963
1074
|
}
|
|
964
1075
|
taskQueue.resume();
|
|
965
1076
|
});
|
|
@@ -996,115 +1107,59 @@ async function watchConnectionStatus(identify) {
|
|
|
996
1107
|
* More details on the license can be found at https://www.monterosa.co/sdk/license
|
|
997
1108
|
*/
|
|
998
1109
|
/**
|
|
1110
|
+
* Process an incoming `Login` / `Logout` broadcast from the parent
|
|
1111
|
+
* application. Updates the local credentials slot, enqueues login/logout
|
|
1112
|
+
* for every existing identify, and forwards the broadcast downstream to
|
|
1113
|
+
* this level's own embedded experiences — the mechanism that cascades a
|
|
1114
|
+
* root-level `setCredentials` through every nested experience.
|
|
1115
|
+
*
|
|
999
1116
|
* @internal
|
|
1000
1117
|
*/
|
|
1001
|
-
function
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
return onSdkMessage(parentApp, async (message) => {
|
|
1007
|
-
switch (message.action) {
|
|
1008
|
-
case IdentifyAction.OnCredentialsUpdated: {
|
|
1009
|
-
identify.credentials = message.payload.data;
|
|
1010
|
-
break;
|
|
1011
|
-
}
|
|
1012
|
-
case IdentifyAction.OnSessionSignatureUpdated: {
|
|
1013
|
-
identify.signature = message.payload.data;
|
|
1014
|
-
break;
|
|
1015
|
-
}
|
|
1016
|
-
case IdentifyAction.OnUserDataUpdated: {
|
|
1017
|
-
identify.userData = message.payload.data;
|
|
1018
|
-
break;
|
|
1019
|
-
}
|
|
1020
|
-
case IdentifyAction.Login: {
|
|
1021
|
-
enqueueLogin(identify, message.payload);
|
|
1022
|
-
break;
|
|
1023
|
-
}
|
|
1024
|
-
case IdentifyAction.Logout: {
|
|
1025
|
-
enqueueLogout(identify);
|
|
1026
|
-
break;
|
|
1027
|
-
}
|
|
1118
|
+
function handleParentMessage(message) {
|
|
1119
|
+
switch (message.action) {
|
|
1120
|
+
case IdentifyAction.Login: {
|
|
1121
|
+
applyLogin(message.payload);
|
|
1122
|
+
break;
|
|
1028
1123
|
}
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
function getOrConfigureSdk(host, projectId) {
|
|
1035
|
-
const existingSdk = getSdks().find((sdk) => sdk.options.projectId === projectId);
|
|
1036
|
-
return existingSdk !== null && existingSdk !== void 0 ? existingSdk : configure({ host, projectId }, projectId);
|
|
1124
|
+
case IdentifyAction.Logout: {
|
|
1125
|
+
applyLogout();
|
|
1126
|
+
break;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1037
1129
|
}
|
|
1038
1130
|
/**
|
|
1039
1131
|
* @internal
|
|
1040
1132
|
*/
|
|
1041
1133
|
function handleExperienceEmbedded(experience) {
|
|
1042
|
-
const identify = getIdentify(experience.sdk);
|
|
1043
|
-
// Send login action with current credentials to the new experience if available.
|
|
1044
|
-
// The bridge queues this message until the experience is initialised.
|
|
1045
|
-
if (identify.credentials) {
|
|
1046
|
-
sendSdkMessage(experience, IdentifyAction.Login, identify.credentials);
|
|
1047
|
-
}
|
|
1048
|
-
const credentialsUpdatedUnsub = onCredentialsUpdated(identify, (data) => {
|
|
1049
|
-
sendSdkMessage(experience, IdentifyAction.OnCredentialsUpdated, {
|
|
1050
|
-
data,
|
|
1051
|
-
});
|
|
1052
|
-
});
|
|
1053
|
-
const signatureUpdatedUnsub = onSignatureUpdated(identify, (data) => {
|
|
1054
|
-
sendSdkMessage(experience, IdentifyAction.OnSessionSignatureUpdated, {
|
|
1055
|
-
data,
|
|
1056
|
-
});
|
|
1057
|
-
});
|
|
1058
|
-
const userDataUpdatedUnsub = onUserDataUpdated(identify, (data) => {
|
|
1059
|
-
sendSdkMessage(experience, IdentifyAction.OnUserDataUpdated, {
|
|
1060
|
-
data,
|
|
1061
|
-
});
|
|
1062
|
-
});
|
|
1063
1134
|
const sdkMessageUnsub = onSdkMessage(experience, async (message) => {
|
|
1064
1135
|
if (!Object.values(IdentifyAction).includes(message.action)) {
|
|
1065
1136
|
return;
|
|
1066
1137
|
}
|
|
1067
|
-
// Extract origin context from payload if available.
|
|
1068
|
-
// New clients include origin (host, projectId) to ensure correct project context
|
|
1069
|
-
// in multilevel integrations. Old clients don't send origin, so we fall back
|
|
1070
|
-
// to the experience's SDK to maintain backward compatibility.
|
|
1071
|
-
const { origin } = message.payload;
|
|
1072
|
-
const originSdk = origin
|
|
1073
|
-
? getOrConfigureSdk(origin.host, origin.projectId)
|
|
1074
|
-
: experience.sdk;
|
|
1075
|
-
const originIdentify = getIdentify(originSdk);
|
|
1076
1138
|
const respond = (payload) => respondToSdkMessage(experience, message, payload);
|
|
1077
1139
|
try {
|
|
1078
1140
|
switch (message.action) {
|
|
1079
1141
|
case IdentifyAction.RequestLogin: {
|
|
1080
|
-
await requestLogin(
|
|
1142
|
+
await requestLogin();
|
|
1081
1143
|
respond();
|
|
1082
1144
|
break;
|
|
1083
1145
|
}
|
|
1084
1146
|
case IdentifyAction.RequestLogout: {
|
|
1085
|
-
await requestLogout(
|
|
1147
|
+
await requestLogout();
|
|
1086
1148
|
respond();
|
|
1087
1149
|
break;
|
|
1088
1150
|
}
|
|
1089
|
-
case IdentifyAction.
|
|
1090
|
-
const data = await
|
|
1151
|
+
case IdentifyAction.GetCredentials: {
|
|
1152
|
+
const data = await getCredentials();
|
|
1091
1153
|
respond({ data });
|
|
1092
1154
|
break;
|
|
1093
1155
|
}
|
|
1094
|
-
case IdentifyAction.GetSessionSignature: {
|
|
1095
|
-
const signature = await getSessionSignatureMemoized(identify, message.payload);
|
|
1096
|
-
respond({ data: signature });
|
|
1097
|
-
break;
|
|
1098
|
-
}
|
|
1099
1156
|
case IdentifyAction.SetCredentials: {
|
|
1100
|
-
await setCredentials(
|
|
1101
|
-
token: message.payload.token,
|
|
1102
|
-
});
|
|
1157
|
+
await setCredentials(message.payload);
|
|
1103
1158
|
respond();
|
|
1104
1159
|
break;
|
|
1105
1160
|
}
|
|
1106
1161
|
case IdentifyAction.ClearCredentials: {
|
|
1107
|
-
await clearCredentials(
|
|
1162
|
+
await clearCredentials();
|
|
1108
1163
|
respond();
|
|
1109
1164
|
break;
|
|
1110
1165
|
}
|
|
@@ -1116,12 +1171,7 @@ function handleExperienceEmbedded(experience) {
|
|
|
1116
1171
|
});
|
|
1117
1172
|
}
|
|
1118
1173
|
});
|
|
1119
|
-
addExperience(experience, [
|
|
1120
|
-
credentialsUpdatedUnsub,
|
|
1121
|
-
signatureUpdatedUnsub,
|
|
1122
|
-
userDataUpdatedUnsub,
|
|
1123
|
-
sdkMessageUnsub,
|
|
1124
|
-
]);
|
|
1174
|
+
addExperience(experience, [sdkMessageUnsub]);
|
|
1125
1175
|
}
|
|
1126
1176
|
/**
|
|
1127
1177
|
* @internal
|
|
@@ -1129,15 +1179,31 @@ function handleExperienceEmbedded(experience) {
|
|
|
1129
1179
|
function handleExperienceUnmounted(experience) {
|
|
1130
1180
|
deleteExperience(experience);
|
|
1131
1181
|
}
|
|
1132
|
-
|
|
1182
|
+
/**
|
|
1183
|
+
* @internal
|
|
1184
|
+
*/
|
|
1185
|
+
function handleExperienceStateChange(experience, state) {
|
|
1133
1186
|
if (state === 'mounted') {
|
|
1134
1187
|
handleExperienceEmbedded(experience);
|
|
1188
|
+
return;
|
|
1135
1189
|
}
|
|
1136
|
-
|
|
1190
|
+
if (state === 'unmounted') {
|
|
1137
1191
|
handleExperienceUnmounted(experience);
|
|
1138
1192
|
}
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1193
|
+
}
|
|
1194
|
+
function subscribeToExperienceLifecycle() {
|
|
1195
|
+
onStateChanged(handleExperienceStateChange);
|
|
1196
|
+
}
|
|
1197
|
+
function connectToParentApplication() {
|
|
1198
|
+
const parentApp = getParentApplication();
|
|
1199
|
+
if (parentApp === null) {
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
onSdkMessage(parentApp, handleParentMessage);
|
|
1203
|
+
pullStateFromParent();
|
|
1204
|
+
}
|
|
1205
|
+
subscribeToExperienceLifecycle();
|
|
1206
|
+
connectToParentApplication();
|
|
1141
1207
|
|
|
1142
|
-
export { IdentifyError, clearCredentials, getIdentify, getUserData, onCredentialsUpdated, onLoginRequestedByExperience, onLogoutRequestedByExperience,
|
|
1208
|
+
export { IdentifyError, clearCredentials, getCredentials, getIdentify, getUserData, onCredentialsUpdated, onLoginRequestedByExperience, onLogoutRequestedByExperience, onStateUpdated, requestLogin, requestLogout, setCredentials, setLoginPolicy };
|
|
1143
1209
|
//# sourceMappingURL=index.js.map
|