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