@monterosa/sdk-identify-kit 2.0.0-rc.3 → 2.0.0-rc.5
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 +212 -257
- 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 +458 -440
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +458 -440
- package/dist/index.js.map +1 -1
- package/dist/login_policy_store.d.ts +28 -0
- package/dist/sdk-identify-kit.d.ts +500 -0
- package/dist/tsdoc-metadata.json +11 -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 store.
|
|
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,78 @@ 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 login policy.
|
|
377
|
+
*
|
|
378
|
+
* - `'auto'`: the SDK automatically logs the user in whenever
|
|
379
|
+
* credentials are available.
|
|
380
|
+
* - `'disabled'`: credentials are tracked but no automatic login is
|
|
381
|
+
* attempted.
|
|
382
|
+
*
|
|
383
|
+
* Each level of a multi-level integration owns its own policy; the
|
|
384
|
+
* value is never propagated to embedded experiences. Idempotent:
|
|
385
|
+
* setting the same policy is a no-op.
|
|
386
|
+
*
|
|
387
|
+
* @param policy - `'auto'` or `'disabled'`.
|
|
388
|
+
*/
|
|
389
|
+
function setLoginPolicy(policy) {
|
|
390
|
+
if (loginPolicyStore.policy === policy) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
loginPolicyStore.policy = policy;
|
|
394
|
+
if (policy !== 'auto') {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
// On transition to 'auto': if credentials are currently set (typical
|
|
398
|
+
// after the non-root module-load pull, or after a setCredentials at
|
|
399
|
+
// the root, or after an upstream Login broadcast has cascaded down),
|
|
400
|
+
// enqueue a login task for each existing identify. If no credentials
|
|
401
|
+
// are set, do nothing — a future credentials arrival via `applyLogin`
|
|
402
|
+
// will trigger the login under this new policy.
|
|
403
|
+
const { credentials } = credentialsStore;
|
|
404
|
+
if (credentials === null) {
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
for (const identify of identifyKits.values()) {
|
|
408
|
+
enqueueLogin(identify, credentials);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Whether the user should be auto-logged in on reconnect.
|
|
413
|
+
*
|
|
414
|
+
* True when the user was previously logged in, the policy is `'auto'`,
|
|
415
|
+
* and credentials are available on the identify instance.
|
|
416
|
+
*
|
|
417
|
+
* @internal
|
|
418
|
+
*/
|
|
419
|
+
function shouldLoginOnReconnect(identify) {
|
|
420
|
+
return (identify.wasLoggedIn &&
|
|
421
|
+
getLoginPolicy() === 'auto' &&
|
|
422
|
+
credentialsStore.credentials !== null);
|
|
423
|
+
}
|
|
297
424
|
/**
|
|
298
425
|
* @internal
|
|
299
426
|
*/
|
|
@@ -330,17 +457,13 @@ async function api(url, token, method = 'GET') {
|
|
|
330
457
|
/**
|
|
331
458
|
* @internal
|
|
332
459
|
*/
|
|
333
|
-
async function
|
|
334
|
-
var _a;
|
|
460
|
+
async function sendParentRequest(action, payload) {
|
|
335
461
|
const parentApp = getParentApplication();
|
|
336
462
|
if (parentApp === null) {
|
|
337
463
|
throw createError(IdentifyError.NoParentApplication, IdentifyErrorMessages);
|
|
338
464
|
}
|
|
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
465
|
try {
|
|
343
|
-
const response = await sendSdkRequest(parentApp, action,
|
|
466
|
+
const response = await sendSdkRequest(parentApp, action, payload);
|
|
344
467
|
const { error, data } = response.payload;
|
|
345
468
|
if (error !== undefined) {
|
|
346
469
|
throw createError(IdentifyError.ParentAppError, IdentifyErrorMessages, error);
|
|
@@ -356,12 +479,6 @@ async function parentAppRequest(identify, action, payload) {
|
|
|
356
479
|
throw err;
|
|
357
480
|
}
|
|
358
481
|
}
|
|
359
|
-
/**
|
|
360
|
-
* @internal
|
|
361
|
-
*/
|
|
362
|
-
function registerIdentifyHook(hook) {
|
|
363
|
-
identifyHooks.push(hook);
|
|
364
|
-
}
|
|
365
482
|
/**
|
|
366
483
|
* @internal
|
|
367
484
|
*/
|
|
@@ -385,6 +502,9 @@ const logoutWithRetry = withRetryAsync(logout);
|
|
|
385
502
|
* @internal
|
|
386
503
|
*/
|
|
387
504
|
async function loginTask(identify, credentials) {
|
|
505
|
+
if (identify.state.state === 'logged_in') {
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
388
508
|
try {
|
|
389
509
|
identify.state = {
|
|
390
510
|
state: 'pending',
|
|
@@ -398,6 +518,11 @@ async function loginTask(identify, credentials) {
|
|
|
398
518
|
}
|
|
399
519
|
}
|
|
400
520
|
catch (err) {
|
|
521
|
+
// Abandon any pending login/logout/sync tasks on failure — letting
|
|
522
|
+
// them run after an error would put the user in an inconsistent
|
|
523
|
+
// state. Note: this also drops tasks for unrelated identifies that
|
|
524
|
+
// share the queue; acceptable because the typical runtime has one
|
|
525
|
+
// identify per project.
|
|
401
526
|
taskQueue.clear();
|
|
402
527
|
identify.state = {
|
|
403
528
|
state: 'error',
|
|
@@ -410,6 +535,9 @@ async function loginTask(identify, credentials) {
|
|
|
410
535
|
* @internal
|
|
411
536
|
*/
|
|
412
537
|
async function logoutTask(identify) {
|
|
538
|
+
if (identify.state.state === 'logged_out') {
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
413
541
|
try {
|
|
414
542
|
identify.state = {
|
|
415
543
|
state: 'pending',
|
|
@@ -423,6 +551,8 @@ async function logoutTask(identify) {
|
|
|
423
551
|
}
|
|
424
552
|
}
|
|
425
553
|
catch (err) {
|
|
554
|
+
// Abandon any pending login/logout/sync tasks on failure — see
|
|
555
|
+
// `loginTask` for the rationale.
|
|
426
556
|
taskQueue.clear();
|
|
427
557
|
identify.state = {
|
|
428
558
|
state: 'error',
|
|
@@ -432,15 +562,55 @@ async function logoutTask(identify) {
|
|
|
432
562
|
}
|
|
433
563
|
}
|
|
434
564
|
/**
|
|
565
|
+
* Enqueue a `loginTask` for the given identify when `policy === 'auto'`.
|
|
566
|
+
* The downstream `Login` broadcast is emitted by {@link applyLogin}.
|
|
567
|
+
*
|
|
435
568
|
* @internal
|
|
436
569
|
*/
|
|
437
570
|
function enqueueLogin(identify, credentials, prioritise = false) {
|
|
438
|
-
if (
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
571
|
+
if (getLoginPolicy() !== 'auto') {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
if (prioritise) {
|
|
575
|
+
taskQueue.enqueueFront(() => loginTask(identify, credentials));
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
taskQueue.enqueue(() => loginTask(identify, credentials));
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Reset the identify's identity-derived caches and enqueue a `logoutTask`
|
|
583
|
+
* when `policy === 'auto'`.
|
|
584
|
+
*
|
|
585
|
+
* @internal
|
|
586
|
+
*/
|
|
587
|
+
function enqueueLogout(identify) {
|
|
588
|
+
identify.userData = null;
|
|
589
|
+
identify.signature = null;
|
|
590
|
+
if (getLoginPolicy() !== 'auto') {
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
taskQueue.enqueue(() => logoutTask(identify));
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Apply new credentials at this level: update the current credentials,
|
|
597
|
+
* enqueue a `loginTask` for every existing identify on the null-to-set
|
|
598
|
+
* transition, and broadcast `Login` downstream to every embedded
|
|
599
|
+
* experience.
|
|
600
|
+
*
|
|
601
|
+
* Idempotent on token refresh: re-setting when credentials are already
|
|
602
|
+
* present updates the value and broadcasts, but does not re-enqueue
|
|
603
|
+
* logins (their `loginTask` would short-circuit on
|
|
604
|
+
* `state === 'logged_in'` anyway).
|
|
605
|
+
*
|
|
606
|
+
* @internal
|
|
607
|
+
*/
|
|
608
|
+
function applyLogin(credentials) {
|
|
609
|
+
const shouldLogin = credentialsStore.credentials === null;
|
|
610
|
+
credentialsStore.credentials = credentials;
|
|
611
|
+
if (shouldLogin) {
|
|
612
|
+
for (const identify of identifyKits.values()) {
|
|
613
|
+
enqueueLogin(identify, credentials);
|
|
444
614
|
}
|
|
445
615
|
}
|
|
446
616
|
for (const experience of getExperiences()) {
|
|
@@ -448,14 +618,50 @@ function enqueueLogin(identify, credentials, prioritise = false) {
|
|
|
448
618
|
}
|
|
449
619
|
}
|
|
450
620
|
/**
|
|
621
|
+
* Clear credentials at this level: clear the current credentials,
|
|
622
|
+
* enqueue a `logoutTask` for every existing identify on the
|
|
623
|
+
* set-to-null transition, and broadcast `Logout` downstream to every
|
|
624
|
+
* embedded experience.
|
|
625
|
+
*
|
|
451
626
|
* @internal
|
|
452
627
|
*/
|
|
453
|
-
function
|
|
454
|
-
|
|
455
|
-
|
|
628
|
+
function applyLogout() {
|
|
629
|
+
const shouldLogout = credentialsStore.credentials !== null;
|
|
630
|
+
credentialsStore.credentials = null;
|
|
631
|
+
if (shouldLogout) {
|
|
632
|
+
for (const identify of identifyKits.values()) {
|
|
633
|
+
enqueueLogout(identify);
|
|
634
|
+
}
|
|
456
635
|
}
|
|
457
636
|
for (const experience of getExperiences()) {
|
|
458
|
-
sendSdkMessage(experience, IdentifyAction.Logout);
|
|
637
|
+
sendSdkMessage(experience, IdentifyAction.Logout, {});
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Pull state from the parent application and apply locally.
|
|
642
|
+
*
|
|
643
|
+
* Fires once at non-root bridge module load, regardless of
|
|
644
|
+
* `loginPolicy` — token presence is the customer-side sign-in state and
|
|
645
|
+
* must mirror upstream whether or not we choose to validate against
|
|
646
|
+
* Enmasse. Best-effort: a missing or non-identify-kit parent silently
|
|
647
|
+
* resolves with no change to the current credentials.
|
|
648
|
+
*
|
|
649
|
+
* Uses {@link applyLogin} so the update cascades downstream to this
|
|
650
|
+
* level's own embedded experiences and per-identify loginTasks are
|
|
651
|
+
* enqueued under `loginPolicy === 'auto'`.
|
|
652
|
+
*
|
|
653
|
+
* @internal
|
|
654
|
+
*/
|
|
655
|
+
async function pullStateFromParent() {
|
|
656
|
+
let credentials;
|
|
657
|
+
try {
|
|
658
|
+
credentials = await getCredentials();
|
|
659
|
+
}
|
|
660
|
+
catch (_a) {
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
if (credentials !== null) {
|
|
664
|
+
applyLogin(credentials);
|
|
459
665
|
}
|
|
460
666
|
}
|
|
461
667
|
function getIdentify(sdkOrOptions, options) {
|
|
@@ -487,94 +693,92 @@ function getIdentify(sdkOrOptions, options) {
|
|
|
487
693
|
sdk = getSdk();
|
|
488
694
|
identifyOptions = {};
|
|
489
695
|
}
|
|
490
|
-
const {
|
|
696
|
+
const { projectId } = sdk.options;
|
|
491
697
|
if (identifyKits.has(projectId)) {
|
|
492
698
|
return identifyKits.get(projectId);
|
|
493
699
|
}
|
|
494
700
|
const identify = new Identify(sdk, identifyOptions);
|
|
495
|
-
for (const hook of identifyHooks) {
|
|
496
|
-
hook(identify);
|
|
497
|
-
}
|
|
498
701
|
watchConnectionStatus(identify);
|
|
499
702
|
identifyKits.set(projectId, identify);
|
|
500
703
|
return identify;
|
|
501
704
|
}
|
|
502
705
|
/**
|
|
503
|
-
*
|
|
706
|
+
* Request a user login.
|
|
707
|
+
*
|
|
708
|
+
* When called from an embedded experience, the request is relayed to
|
|
709
|
+
* the parent application — the host that owns the auth UI handles it.
|
|
504
710
|
*
|
|
505
711
|
* @example
|
|
506
712
|
* ```javascript
|
|
507
713
|
* import { configure } from '@monterosa/sdk-core';
|
|
508
|
-
* import {
|
|
714
|
+
* import { requestLogin } from '@monterosa/sdk-identify-kit';
|
|
509
715
|
*
|
|
510
716
|
* configure({ host: '...', projectId: '...' });
|
|
511
717
|
*
|
|
512
718
|
* try {
|
|
513
|
-
*
|
|
514
|
-
*
|
|
515
|
-
* await requestLogin(identify);
|
|
516
|
-
*
|
|
719
|
+
* await requestLogin();
|
|
517
720
|
* console.log('Login request successful');
|
|
518
721
|
* } catch (err) {
|
|
519
|
-
* console.error('Error requesting login:',
|
|
722
|
+
* console.error('Error requesting login:', err.message)
|
|
520
723
|
* }
|
|
521
724
|
* ```
|
|
522
725
|
*
|
|
523
|
-
* @
|
|
524
|
-
*
|
|
525
|
-
* the Monterosa SDK, the function delegates to the parent app
|
|
526
|
-
* to handle the login process.
|
|
527
|
-
*
|
|
528
|
-
* @param identify - An instance of the `IdentifyKit` class used for user
|
|
529
|
-
* identification.
|
|
530
|
-
* @returns A Promise that resolves with `void` when the login request
|
|
531
|
-
* is completed.
|
|
726
|
+
* @returns A Promise that resolves once the login request has been
|
|
727
|
+
* delivered.
|
|
532
728
|
*/
|
|
533
|
-
async function requestLogin(
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
await parentAppRequest(identify, IdentifyAction.RequestLogin);
|
|
729
|
+
async function requestLogin() {
|
|
730
|
+
if (getParentApplication() !== null) {
|
|
731
|
+
await sendParentRequest(IdentifyAction.RequestLogin);
|
|
537
732
|
return;
|
|
538
733
|
}
|
|
539
|
-
|
|
734
|
+
requestsEmitter.emit(IdentifyEvent.LoginRequested);
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Read the current credentials.
|
|
738
|
+
*
|
|
739
|
+
* When called from an embedded experience, fetches the credentials
|
|
740
|
+
* from the parent application so the caller always sees the
|
|
741
|
+
* authoritative value.
|
|
742
|
+
*
|
|
743
|
+
* @returns A Promise that resolves to the current credentials, or
|
|
744
|
+
* `null` if none are set.
|
|
745
|
+
*/
|
|
746
|
+
async function getCredentials() {
|
|
747
|
+
if (getParentApplication() === null) {
|
|
748
|
+
return credentialsStore.credentials;
|
|
749
|
+
}
|
|
750
|
+
return sendParentRequest(IdentifyAction.GetCredentials);
|
|
540
751
|
}
|
|
541
752
|
/**
|
|
542
|
-
*
|
|
753
|
+
* Request a user logout.
|
|
754
|
+
*
|
|
755
|
+
* When called from an embedded experience, the request is relayed to
|
|
756
|
+
* the parent application — the host that owns the auth UI handles it.
|
|
543
757
|
*
|
|
544
758
|
* @example
|
|
545
759
|
* ```javascript
|
|
546
|
-
* import {
|
|
547
|
-
* import {
|
|
760
|
+
* import { configure } from '@monterosa/sdk-core';
|
|
761
|
+
* import { requestLogout } from '@monterosa/sdk-identify-kit';
|
|
548
762
|
*
|
|
549
|
-
*
|
|
550
|
-
* const identify = getIdentify(space);
|
|
763
|
+
* configure({ host: '...', projectId: '...' });
|
|
551
764
|
*
|
|
552
765
|
* try {
|
|
553
|
-
* await requestLogout(
|
|
554
|
-
*
|
|
766
|
+
* await requestLogout();
|
|
555
767
|
* console.log('Logout request successful');
|
|
556
768
|
* } catch (err) {
|
|
557
|
-
* console.error('Error requesting logout:',
|
|
769
|
+
* console.error('Error requesting logout:', err.message)
|
|
558
770
|
* }
|
|
559
771
|
* ```
|
|
560
772
|
*
|
|
561
|
-
* @
|
|
562
|
-
*
|
|
563
|
-
* the Space, the function delegates to the parent app
|
|
564
|
-
* to handle the logout process.
|
|
565
|
-
*
|
|
566
|
-
* @param identify - An instance of the `IdentifyKit` class used for user
|
|
567
|
-
* identification.
|
|
568
|
-
* @returns A Promise that resolves with `void` when the logout request
|
|
569
|
-
* is completed.
|
|
773
|
+
* @returns A Promise that resolves once the logout request has been
|
|
774
|
+
* delivered.
|
|
570
775
|
*/
|
|
571
|
-
async function requestLogout(
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
await parentAppRequest(identify, IdentifyAction.RequestLogout);
|
|
776
|
+
async function requestLogout() {
|
|
777
|
+
if (getParentApplication() !== null) {
|
|
778
|
+
await sendParentRequest(IdentifyAction.RequestLogout);
|
|
575
779
|
return;
|
|
576
780
|
}
|
|
577
|
-
|
|
781
|
+
requestsEmitter.emit(IdentifyEvent.LogoutRequested);
|
|
578
782
|
}
|
|
579
783
|
/**
|
|
580
784
|
* @internal
|
|
@@ -593,11 +797,6 @@ async function requestLogout(identify) {
|
|
|
593
797
|
* @returns A Promise that resolves to a `Signature` object.
|
|
594
798
|
*/
|
|
595
799
|
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
800
|
if (identify.signature !== null) {
|
|
602
801
|
return identify.signature;
|
|
603
802
|
}
|
|
@@ -608,148 +807,118 @@ async function getSessionSignature(identify, credentials) {
|
|
|
608
807
|
return signature;
|
|
609
808
|
}
|
|
610
809
|
/**
|
|
611
|
-
*
|
|
810
|
+
* @internal
|
|
811
|
+
*
|
|
812
|
+
* A memoized version of the `getSessionSignature` function. Memo key is
|
|
813
|
+
* the credentials token, so both leaf-side and bridge-side callers share
|
|
814
|
+
* the same cache for the same token.
|
|
612
815
|
*/
|
|
613
816
|
const getSessionSignatureMemoized = memoizePromise(getSessionSignature, (identify, credentials) => credentials.token, {
|
|
614
817
|
clearOnResolve: true,
|
|
615
818
|
clearOnReject: true,
|
|
616
819
|
});
|
|
617
820
|
/**
|
|
618
|
-
*
|
|
619
|
-
*
|
|
821
|
+
* Fetch user data for the given credentials.
|
|
822
|
+
*
|
|
823
|
+
* Credentials are required explicitly. Obtain a value via
|
|
824
|
+
* {@link getCredentials} or the {@link onCredentialsUpdated} callback.
|
|
620
825
|
*
|
|
621
826
|
* @example
|
|
622
827
|
* ```javascript
|
|
623
828
|
* import { configure } from '@monterosa/sdk-core';
|
|
624
|
-
* import {
|
|
829
|
+
* import {
|
|
830
|
+
* getIdentify,
|
|
831
|
+
* getUserData,
|
|
832
|
+
* getCredentials,
|
|
833
|
+
* } from '@monterosa/sdk-identify-kit';
|
|
625
834
|
*
|
|
626
835
|
* configure({ host: '...', projectId: '...' });
|
|
627
836
|
*
|
|
628
837
|
* const identify = getIdentify();
|
|
629
|
-
* const
|
|
838
|
+
* const credentials = await getCredentials();
|
|
630
839
|
*
|
|
631
|
-
*
|
|
840
|
+
* if (credentials !== null) {
|
|
841
|
+
* const userData = await getUserData(identify, credentials);
|
|
842
|
+
* console.log('User data:', userData);
|
|
843
|
+
* }
|
|
632
844
|
* ```
|
|
633
845
|
*
|
|
634
846
|
* @remarks
|
|
635
|
-
*
|
|
636
|
-
*
|
|
637
|
-
*
|
|
638
|
-
*
|
|
639
|
-
*
|
|
640
|
-
*
|
|
641
|
-
*
|
|
642
|
-
* @param identify - An instance of `IdentifyKit` that provides the user
|
|
643
|
-
* identification functionality.
|
|
644
|
-
* @returns A Promise that resolves to a key-value object representing user data.
|
|
645
|
-
* The structure and content of the user data object depend on the identify
|
|
646
|
-
* service provider and may vary. It typically contains information about the user,
|
|
647
|
-
* but the specific fields are determined by the Identify service provider.
|
|
847
|
+
* Cached after the first successful fetch and reset when credentials
|
|
848
|
+
* are cleared.
|
|
849
|
+
*
|
|
850
|
+
* @param identify - The IdentifyKit instance.
|
|
851
|
+
* @param credentials - The user's authentication credentials.
|
|
852
|
+
* @returns A Promise that resolves to a key-value object of user data.
|
|
853
|
+
* The structure depends on the identify service provider.
|
|
648
854
|
*/
|
|
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
|
|
855
|
+
async function getUserData(identify, credentials) {
|
|
656
856
|
if (identify.userData !== null) {
|
|
657
857
|
return identify.userData;
|
|
658
858
|
}
|
|
659
|
-
if (identify.credentials === null) {
|
|
660
|
-
throw createError(IdentifyError.NoCredentials, IdentifyErrorMessages);
|
|
661
|
-
}
|
|
662
859
|
const url = await identify.getUrl('/user');
|
|
663
|
-
const { data } = await api(url,
|
|
860
|
+
const { data } = await api(url, credentials.token);
|
|
664
861
|
identify.userData = data;
|
|
665
862
|
return data;
|
|
666
863
|
}
|
|
667
864
|
/**
|
|
668
|
-
*
|
|
865
|
+
* Set the user's authentication credentials.
|
|
866
|
+
*
|
|
867
|
+
* The credentials become the active credentials for the entire
|
|
868
|
+
* integration. When called from an embedded experience, the call is
|
|
869
|
+
* relayed to the parent application so that every level of the
|
|
870
|
+
* integration sees the new value.
|
|
669
871
|
*
|
|
670
872
|
* @example
|
|
671
873
|
* ```javascript
|
|
672
874
|
* import { configure } from '@monterosa/sdk-core';
|
|
673
|
-
* import {
|
|
875
|
+
* import { setCredentials } from '@monterosa/sdk-identify-kit';
|
|
674
876
|
*
|
|
675
877
|
* configure({ host: '...', projectId: '...' });
|
|
676
878
|
*
|
|
677
|
-
*
|
|
678
|
-
* const identify = getIdentify();
|
|
679
|
-
*
|
|
680
|
-
* await setCredentials(identify, credentials)
|
|
879
|
+
* await setCredentials({ token: 'abc123' });
|
|
681
880
|
* ```
|
|
682
881
|
*
|
|
683
|
-
* @
|
|
684
|
-
*
|
|
685
|
-
*
|
|
686
|
-
* to set user credentials.
|
|
687
|
-
*
|
|
688
|
-
* - If the request is successful, the function resolves to `void`.
|
|
689
|
-
* If not, a `MonterosaError` is thrown.
|
|
690
|
-
*
|
|
691
|
-
* @param identify - An instance of `IdentifyKit` that provides the user
|
|
692
|
-
* identification functionality.
|
|
693
|
-
* @param credentials - An object representing the user's authentication
|
|
694
|
-
* credentials.
|
|
695
|
-
* @returns A Promise that resolves to `void`.
|
|
882
|
+
* @param credentials - The user's authentication credentials.
|
|
883
|
+
* @returns A Promise that resolves once the credentials have been
|
|
884
|
+
* applied.
|
|
696
885
|
*/
|
|
697
|
-
async function setCredentials(
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
await parentAppRequest(identify, IdentifyAction.SetCredentials, credentials);
|
|
886
|
+
async function setCredentials(credentials) {
|
|
887
|
+
if (getParentApplication() !== null) {
|
|
888
|
+
await sendParentRequest(IdentifyAction.SetCredentials, credentials);
|
|
701
889
|
return;
|
|
702
890
|
}
|
|
703
|
-
|
|
704
|
-
identify.credentials = credentials;
|
|
705
|
-
if (shouldLogin) {
|
|
706
|
-
enqueueLogin(identify, credentials);
|
|
707
|
-
}
|
|
891
|
+
applyLogin(credentials);
|
|
708
892
|
}
|
|
709
893
|
/**
|
|
710
|
-
*
|
|
894
|
+
* Clear the user's authentication credentials.
|
|
895
|
+
*
|
|
896
|
+
* When called from an embedded experience, the call is relayed to the
|
|
897
|
+
* parent application so that every level of the integration is
|
|
898
|
+
* cleared.
|
|
711
899
|
*
|
|
712
900
|
* @example
|
|
713
901
|
* ```javascript
|
|
714
902
|
* import { configure } from '@monterosa/sdk-core';
|
|
715
|
-
* import {
|
|
903
|
+
* import { clearCredentials } from '@monterosa/sdk-identify-kit';
|
|
716
904
|
*
|
|
717
905
|
* configure({ host: '...', projectId: '...' });
|
|
718
906
|
*
|
|
719
|
-
*
|
|
720
|
-
*
|
|
721
|
-
* await clearCredentials(identify);
|
|
907
|
+
* await clearCredentials();
|
|
722
908
|
* ```
|
|
723
909
|
*
|
|
724
|
-
* @
|
|
725
|
-
*
|
|
726
|
-
* the Monterosa SDK, the function delegates to the parent app
|
|
727
|
-
* to clear user credentials.
|
|
728
|
-
*
|
|
729
|
-
* - If the request is successful, the function resolves to `void`.
|
|
730
|
-
* If not, a `MonterosaError` is thrown.
|
|
731
|
-
*
|
|
732
|
-
* @param identify - An instance of `IdentifyKit` that provides the user
|
|
733
|
-
* identification functionality.
|
|
734
|
-
* @returns A Promise that resolves to `void`.
|
|
910
|
+
* @returns A Promise that resolves once the credentials have been
|
|
911
|
+
* cleared.
|
|
735
912
|
*/
|
|
736
|
-
async function clearCredentials(
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
await parentAppRequest(identify, IdentifyAction.ClearCredentials);
|
|
913
|
+
async function clearCredentials() {
|
|
914
|
+
if (getParentApplication() !== null) {
|
|
915
|
+
await sendParentRequest(IdentifyAction.ClearCredentials);
|
|
740
916
|
return;
|
|
741
917
|
}
|
|
742
|
-
|
|
743
|
-
identify.credentials = null;
|
|
744
|
-
identify.userData = null;
|
|
745
|
-
identify.signature = null;
|
|
746
|
-
if (shouldLogout) {
|
|
747
|
-
enqueueLogout(identify);
|
|
748
|
-
}
|
|
918
|
+
applyLogout();
|
|
749
919
|
}
|
|
750
920
|
/**
|
|
751
|
-
*
|
|
752
|
-
* object associated with the `IdentifyKit` instance is updated.
|
|
921
|
+
* Register a callback for `LoginState` updates on the given identify.
|
|
753
922
|
*
|
|
754
923
|
* @example
|
|
755
924
|
* ```javascript
|
|
@@ -763,203 +932,97 @@ async function clearCredentials(identify) {
|
|
|
763
932
|
* const unsubscribe = onStateUpdated(identify, (state) => {
|
|
764
933
|
* console.log("State updated:", state);
|
|
765
934
|
* });
|
|
766
|
-
*
|
|
767
|
-
* // Call unsubscribe() to unregister the callback function
|
|
768
|
-
* // unsubscribe();
|
|
769
935
|
* ```
|
|
770
936
|
*
|
|
771
|
-
* @param identify -
|
|
772
|
-
*
|
|
773
|
-
* @
|
|
774
|
-
* called with the updated `LoginState` object as its only argument.
|
|
775
|
-
* @returns An `Unsubscribe` function that can be called to unregister
|
|
776
|
-
* the callback function.
|
|
937
|
+
* @param identify - The IdentifyKit instance.
|
|
938
|
+
* @param callback - Called with the updated `LoginState`.
|
|
939
|
+
* @returns An `Unsubscribe` function.
|
|
777
940
|
*/
|
|
778
941
|
function onStateUpdated(identify, callback) {
|
|
779
942
|
return subscribe(identify, IdentifyEvent.StateUpdated, callback);
|
|
780
943
|
}
|
|
781
944
|
/**
|
|
782
|
-
*
|
|
783
|
-
* object associated with the `IdentifyKit` instance is updated.
|
|
945
|
+
* Register a callback for updates to the current credentials.
|
|
784
946
|
*
|
|
785
947
|
* @example
|
|
786
948
|
* ```javascript
|
|
787
949
|
* import { configure } from '@monterosa/sdk-core';
|
|
788
|
-
* import {
|
|
950
|
+
* import { onCredentialsUpdated } from '@monterosa/sdk-identify-kit';
|
|
789
951
|
*
|
|
790
952
|
* configure({ host: '...', projectId: '...' });
|
|
791
953
|
*
|
|
792
|
-
* const
|
|
793
|
-
*
|
|
794
|
-
* const unsubscribe = onCredentialsUpdated(identify, (credentials) => {
|
|
954
|
+
* const unsubscribe = onCredentialsUpdated((credentials) => {
|
|
795
955
|
* if (credentials !== null) {
|
|
796
956
|
* console.log("Credentials updated:", credentials);
|
|
797
957
|
* } else {
|
|
798
958
|
* console.log("Credentials cleared.");
|
|
799
959
|
* }
|
|
800
960
|
* });
|
|
801
|
-
*
|
|
802
|
-
* // Call unsubscribe() to unregister the callback function
|
|
803
|
-
* // unsubscribe();
|
|
804
961
|
* ```
|
|
805
962
|
*
|
|
806
|
-
* @param
|
|
807
|
-
*
|
|
808
|
-
* @
|
|
809
|
-
* called with the updated `Credentials` object as its only argument.
|
|
810
|
-
* If the value `null` is received, it indicates that the signature has
|
|
811
|
-
* been cleared
|
|
812
|
-
* @returns An `Unsubscribe` function that can be called to unregister
|
|
813
|
-
* the callback function.
|
|
963
|
+
* @param callback - Called with the updated `Credentials`, or `null`
|
|
964
|
+
* when credentials are cleared.
|
|
965
|
+
* @returns An `Unsubscribe` function.
|
|
814
966
|
*/
|
|
815
|
-
function onCredentialsUpdated(
|
|
816
|
-
return subscribe(
|
|
967
|
+
function onCredentialsUpdated(callback) {
|
|
968
|
+
return credentialsStore.subscribe(callback);
|
|
817
969
|
}
|
|
818
970
|
/**
|
|
819
|
-
*
|
|
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: '...' });
|
|
971
|
+
* Register a callback for login requests.
|
|
828
972
|
*
|
|
829
|
-
*
|
|
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
|
|
849
|
-
* @returns An `Unsubscribe` function that can be called to unregister
|
|
850
|
-
* the callback function.
|
|
851
|
-
*/
|
|
852
|
-
function onSignatureUpdated(identify, callback) {
|
|
853
|
-
return subscribe(identify, IdentifyEvent.SignatureUpdated, callback);
|
|
854
|
-
}
|
|
855
|
-
/**
|
|
856
|
-
* Registers a callback function that will be called whenever the `UserData`
|
|
857
|
-
* object associated with the `IdentifyKit` instance is updated.
|
|
973
|
+
* Fires when {@link requestLogin} is called at this level — whether by
|
|
974
|
+
* local code or relayed up from an embedded experience.
|
|
858
975
|
*
|
|
859
976
|
* @example
|
|
860
977
|
* ```javascript
|
|
861
978
|
* import { configure } from '@monterosa/sdk-core';
|
|
862
|
-
* import {
|
|
979
|
+
* import { onLoginRequestedByExperience } from '@monterosa/sdk-identify-kit';
|
|
863
980
|
*
|
|
864
981
|
* configure({ host: '...', projectId: '...' });
|
|
865
982
|
*
|
|
866
|
-
* const
|
|
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
|
-
* }
|
|
983
|
+
* const unsubscribe = onLoginRequestedByExperience(() => {
|
|
984
|
+
* showLoginForm();
|
|
874
985
|
* });
|
|
875
|
-
*
|
|
876
|
-
* // Call unsubscribe() to unregister the callback function
|
|
877
|
-
* // unsubscribe();
|
|
878
986
|
* ```
|
|
879
987
|
*
|
|
880
|
-
* @param
|
|
881
|
-
*
|
|
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.
|
|
988
|
+
* @param callback - Called when a login is requested.
|
|
989
|
+
* @returns An `Unsubscribe` function.
|
|
888
990
|
*/
|
|
889
|
-
function
|
|
890
|
-
return subscribe(
|
|
991
|
+
function onLoginRequestedByExperience(callback) {
|
|
992
|
+
return subscribe(requestsEmitter, IdentifyEvent.LoginRequested, callback);
|
|
891
993
|
}
|
|
892
994
|
/**
|
|
893
|
-
*
|
|
894
|
-
*
|
|
995
|
+
* Register a callback for logout requests.
|
|
996
|
+
*
|
|
997
|
+
* Fires when {@link requestLogout} is called at this level — whether
|
|
998
|
+
* by local code or relayed up from an embedded experience.
|
|
895
999
|
*
|
|
896
1000
|
* @example
|
|
897
1001
|
* ```javascript
|
|
898
1002
|
* import { configure } from '@monterosa/sdk-core';
|
|
899
|
-
* import {
|
|
1003
|
+
* import { onLogoutRequestedByExperience } from '@monterosa/sdk-identify-kit';
|
|
900
1004
|
*
|
|
901
1005
|
* configure({ host: '...', projectId: '...' });
|
|
902
1006
|
*
|
|
903
|
-
* const
|
|
904
|
-
*
|
|
905
|
-
* const unsubscribe = onLoginRequestedByExperience(identify, () => {
|
|
906
|
-
* showLoginForm();
|
|
907
|
-
* });
|
|
908
|
-
*
|
|
909
|
-
* // Call unsubscribe() to unregister the callback function
|
|
910
|
-
* // unsubscribe();
|
|
911
|
-
* ```
|
|
912
|
-
*
|
|
913
|
-
* @param identify - An instance of `IdentifyKit` that provides the user
|
|
914
|
-
* identification functionality.
|
|
915
|
-
* @param callback - The callback function to register. This function will
|
|
916
|
-
* be called when a login is requested by an Experience.
|
|
917
|
-
* @returns An `Unsubscribe` function that can be called to unregister
|
|
918
|
-
* the callback function.
|
|
919
|
-
*/
|
|
920
|
-
function onLoginRequestedByExperience(identify, callback) {
|
|
921
|
-
return subscribe(identify, IdentifyEvent.LoginRequested, callback);
|
|
922
|
-
}
|
|
923
|
-
/**
|
|
924
|
-
* Registers a callback function that will be called when a logout is requested
|
|
925
|
-
* by an Experience.
|
|
926
|
-
*
|
|
927
|
-
* @example
|
|
928
|
-
* ```javascript
|
|
929
|
-
* import { getSpace } from '@monterosa/sdk-core';
|
|
930
|
-
* import { getIdentify, onLogoutRequestedByExperience } from '@monterosa/sdk-identify-kit';
|
|
931
|
-
*
|
|
932
|
-
* const space = getSpace('host', 'space-id');
|
|
933
|
-
* const identify = getIdentify(space);
|
|
934
|
-
*
|
|
935
|
-
* const unsubscribe = onLogoutRequestedByExperience(identify, () => {
|
|
936
|
-
* // logout requested by experience
|
|
937
|
-
* // perform logout from Auth service
|
|
1007
|
+
* const unsubscribe = onLogoutRequestedByExperience(() => {
|
|
1008
|
+
* // perform logout from auth service
|
|
938
1009
|
* });
|
|
939
|
-
*
|
|
940
|
-
* // Call unsubscribe() to unregister the callback function
|
|
941
|
-
* // unsubscribe();
|
|
942
1010
|
* ```
|
|
943
1011
|
*
|
|
944
|
-
* @param
|
|
945
|
-
*
|
|
946
|
-
* @param callback - The callback function to register. This function will
|
|
947
|
-
* be called when a logout is requested by an Experience.
|
|
948
|
-
* @returns An `Unsubscribe` function that can be called to unregister
|
|
949
|
-
* the callback function.
|
|
1012
|
+
* @param callback - Called when a logout is requested.
|
|
1013
|
+
* @returns An `Unsubscribe` function.
|
|
950
1014
|
*/
|
|
951
|
-
function onLogoutRequestedByExperience(
|
|
952
|
-
return subscribe(
|
|
1015
|
+
function onLogoutRequestedByExperience(callback) {
|
|
1016
|
+
return subscribe(requestsEmitter, IdentifyEvent.LogoutRequested, callback);
|
|
953
1017
|
}
|
|
954
1018
|
/**
|
|
955
|
-
*
|
|
956
1019
|
* @internal
|
|
957
1020
|
*/
|
|
958
1021
|
async function watchConnectionStatus(identify) {
|
|
959
1022
|
const conn = await getConnect(identify.sdk.options.host);
|
|
960
1023
|
onConnected(conn, () => {
|
|
961
|
-
if (identify
|
|
962
|
-
enqueueLogin(identify,
|
|
1024
|
+
if (shouldLoginOnReconnect(identify)) {
|
|
1025
|
+
enqueueLogin(identify, credentialsStore.credentials, true);
|
|
963
1026
|
}
|
|
964
1027
|
taskQueue.resume();
|
|
965
1028
|
});
|
|
@@ -996,115 +1059,59 @@ async function watchConnectionStatus(identify) {
|
|
|
996
1059
|
* More details on the license can be found at https://www.monterosa.co/sdk/license
|
|
997
1060
|
*/
|
|
998
1061
|
/**
|
|
1062
|
+
* Process an incoming `Login` / `Logout` broadcast from the parent
|
|
1063
|
+
* application. Updates the local current credentials, enqueues login/logout
|
|
1064
|
+
* for every existing identify, and forwards the broadcast downstream to
|
|
1065
|
+
* this level's own embedded experiences — the mechanism that cascades a
|
|
1066
|
+
* root-level `setCredentials` through every nested experience.
|
|
1067
|
+
*
|
|
999
1068
|
* @internal
|
|
1000
1069
|
*/
|
|
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
|
-
}
|
|
1070
|
+
function handleParentMessage(message) {
|
|
1071
|
+
switch (message.action) {
|
|
1072
|
+
case IdentifyAction.Login: {
|
|
1073
|
+
applyLogin(message.payload);
|
|
1074
|
+
break;
|
|
1028
1075
|
}
|
|
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);
|
|
1076
|
+
case IdentifyAction.Logout: {
|
|
1077
|
+
applyLogout();
|
|
1078
|
+
break;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1037
1081
|
}
|
|
1038
1082
|
/**
|
|
1039
1083
|
* @internal
|
|
1040
1084
|
*/
|
|
1041
1085
|
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
1086
|
const sdkMessageUnsub = onSdkMessage(experience, async (message) => {
|
|
1064
1087
|
if (!Object.values(IdentifyAction).includes(message.action)) {
|
|
1065
1088
|
return;
|
|
1066
1089
|
}
|
|
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
1090
|
const respond = (payload) => respondToSdkMessage(experience, message, payload);
|
|
1077
1091
|
try {
|
|
1078
1092
|
switch (message.action) {
|
|
1079
1093
|
case IdentifyAction.RequestLogin: {
|
|
1080
|
-
await requestLogin(
|
|
1094
|
+
await requestLogin();
|
|
1081
1095
|
respond();
|
|
1082
1096
|
break;
|
|
1083
1097
|
}
|
|
1084
1098
|
case IdentifyAction.RequestLogout: {
|
|
1085
|
-
await requestLogout(
|
|
1099
|
+
await requestLogout();
|
|
1086
1100
|
respond();
|
|
1087
1101
|
break;
|
|
1088
1102
|
}
|
|
1089
|
-
case IdentifyAction.
|
|
1090
|
-
const data = await
|
|
1103
|
+
case IdentifyAction.GetCredentials: {
|
|
1104
|
+
const data = await getCredentials();
|
|
1091
1105
|
respond({ data });
|
|
1092
1106
|
break;
|
|
1093
1107
|
}
|
|
1094
|
-
case IdentifyAction.GetSessionSignature: {
|
|
1095
|
-
const signature = await getSessionSignatureMemoized(identify, message.payload);
|
|
1096
|
-
respond({ data: signature });
|
|
1097
|
-
break;
|
|
1098
|
-
}
|
|
1099
1108
|
case IdentifyAction.SetCredentials: {
|
|
1100
|
-
await setCredentials(
|
|
1101
|
-
token: message.payload.token,
|
|
1102
|
-
});
|
|
1109
|
+
await setCredentials(message.payload);
|
|
1103
1110
|
respond();
|
|
1104
1111
|
break;
|
|
1105
1112
|
}
|
|
1106
1113
|
case IdentifyAction.ClearCredentials: {
|
|
1107
|
-
await clearCredentials(
|
|
1114
|
+
await clearCredentials();
|
|
1108
1115
|
respond();
|
|
1109
1116
|
break;
|
|
1110
1117
|
}
|
|
@@ -1116,12 +1123,7 @@ function handleExperienceEmbedded(experience) {
|
|
|
1116
1123
|
});
|
|
1117
1124
|
}
|
|
1118
1125
|
});
|
|
1119
|
-
addExperience(experience, [
|
|
1120
|
-
credentialsUpdatedUnsub,
|
|
1121
|
-
signatureUpdatedUnsub,
|
|
1122
|
-
userDataUpdatedUnsub,
|
|
1123
|
-
sdkMessageUnsub,
|
|
1124
|
-
]);
|
|
1126
|
+
addExperience(experience, [sdkMessageUnsub]);
|
|
1125
1127
|
}
|
|
1126
1128
|
/**
|
|
1127
1129
|
* @internal
|
|
@@ -1129,15 +1131,31 @@ function handleExperienceEmbedded(experience) {
|
|
|
1129
1131
|
function handleExperienceUnmounted(experience) {
|
|
1130
1132
|
deleteExperience(experience);
|
|
1131
1133
|
}
|
|
1132
|
-
|
|
1134
|
+
/**
|
|
1135
|
+
* @internal
|
|
1136
|
+
*/
|
|
1137
|
+
function handleExperienceStateChange(experience, state) {
|
|
1133
1138
|
if (state === 'mounted') {
|
|
1134
1139
|
handleExperienceEmbedded(experience);
|
|
1140
|
+
return;
|
|
1135
1141
|
}
|
|
1136
|
-
|
|
1142
|
+
if (state === 'unmounted') {
|
|
1137
1143
|
handleExperienceUnmounted(experience);
|
|
1138
1144
|
}
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1145
|
+
}
|
|
1146
|
+
function subscribeToExperienceLifecycle() {
|
|
1147
|
+
onStateChanged(handleExperienceStateChange);
|
|
1148
|
+
}
|
|
1149
|
+
function connectToParentApplication() {
|
|
1150
|
+
const parentApp = getParentApplication();
|
|
1151
|
+
if (parentApp === null) {
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
onSdkMessage(parentApp, handleParentMessage);
|
|
1155
|
+
pullStateFromParent();
|
|
1156
|
+
}
|
|
1157
|
+
subscribeToExperienceLifecycle();
|
|
1158
|
+
connectToParentApplication();
|
|
1141
1159
|
|
|
1142
|
-
export { IdentifyError, clearCredentials, getIdentify, getUserData, onCredentialsUpdated, onLoginRequestedByExperience, onLogoutRequestedByExperience,
|
|
1160
|
+
export { IdentifyError, clearCredentials, getCredentials, getIdentify, getUserData, onCredentialsUpdated, onLoginRequestedByExperience, onLogoutRequestedByExperience, onStateUpdated, requestLogin, requestLogout, setCredentials, setLoginPolicy };
|
|
1143
1161
|
//# sourceMappingURL=index.js.map
|