@uniformdev/context 18.17.1-alpha.13 → 18.19.0

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/api.js CHANGED
@@ -240,11 +240,13 @@ var _AggregateClient = class extends ApiClient {
240
240
  constructor(options) {
241
241
  super(options);
242
242
  }
243
+ /** Fetches all aggregates for a project */
243
244
  async get(options) {
244
245
  const { projectId } = this.options;
245
246
  const fetchUri = this.createUrl(__privateGet(_AggregateClient, _url), { ...options, projectId });
246
247
  return await this.apiClient(fetchUri);
247
248
  }
249
+ /** Updates or creates (based on id) an Aggregate */
248
250
  async upsert(body) {
249
251
  const fetchUri = this.createUrl(__privateGet(_AggregateClient, _url));
250
252
  await this.apiClient(fetchUri, {
@@ -253,6 +255,7 @@ var _AggregateClient = class extends ApiClient {
253
255
  expectNoContent: true
254
256
  });
255
257
  }
258
+ /** Deletes an Aggregate */
256
259
  async remove(body) {
257
260
  const fetchUri = this.createUrl(__privateGet(_AggregateClient, _url));
258
261
  await this.apiClient(fetchUri, {
@@ -317,6 +320,7 @@ var _DimensionClient = class extends ApiClient {
317
320
  constructor(options) {
318
321
  super(options);
319
322
  }
323
+ /** Fetches the known score dimensions for a project */
320
324
  async get(options) {
321
325
  const { projectId } = this.options;
322
326
  const fetchUri = this.createUrl(__privateGet(_DimensionClient, _url2), { ...options, projectId });
@@ -343,11 +347,13 @@ var _EnrichmentClient = class extends ApiClient {
343
347
  constructor(options) {
344
348
  super(options);
345
349
  }
350
+ /** Fetches all enrichments and values for a project, grouped by category */
346
351
  async get(options) {
347
352
  const { projectId } = this.options;
348
353
  const fetchUri = this.createUrl(__privateGet(_EnrichmentClient, _url3), { ...options, projectId });
349
354
  return await this.apiClient(fetchUri);
350
355
  }
356
+ /** Updates or creates (based on id) an enrichment category */
351
357
  async upsertCategory(body) {
352
358
  const fetchUri = this.createUrl(__privateGet(_EnrichmentClient, _url3));
353
359
  await this.apiClient(fetchUri, {
@@ -356,6 +362,7 @@ var _EnrichmentClient = class extends ApiClient {
356
362
  expectNoContent: true
357
363
  });
358
364
  }
365
+ /** Deletes an enrichment category */
359
366
  async removeCategory(body) {
360
367
  const fetchUri = this.createUrl(__privateGet(_EnrichmentClient, _url3));
361
368
  await this.apiClient(fetchUri, {
@@ -364,6 +371,7 @@ var _EnrichmentClient = class extends ApiClient {
364
371
  expectNoContent: true
365
372
  });
366
373
  }
374
+ /** Updates or creates (based on id) an enrichment value within an enrichment category */
367
375
  async upsertValue(body) {
368
376
  const fetchUri = this.createUrl(__privateGet(_EnrichmentClient, _valueUrl));
369
377
  await this.apiClient(fetchUri, {
@@ -372,6 +380,7 @@ var _EnrichmentClient = class extends ApiClient {
372
380
  expectNoContent: true
373
381
  });
374
382
  }
383
+ /** Deletes an enrichment value within an enrichment category. The category is left alone. */
375
384
  async removeValue(body) {
376
385
  const fetchUri = this.createUrl(__privateGet(_EnrichmentClient, _valueUrl));
377
386
  await this.apiClient(fetchUri, {
@@ -403,11 +412,13 @@ var _ManifestClient = class extends ApiClient {
403
412
  constructor(options) {
404
413
  super(options);
405
414
  }
415
+ /** Fetches the Context manifest for a project */
406
416
  async get(options) {
407
417
  const { projectId } = this.options;
408
418
  const fetchUri = this.createUrl(__privateGet(_ManifestClient, _url4), { ...options, projectId });
409
419
  return await this.apiClient(fetchUri);
410
420
  }
421
+ /** Publishes the Context manifest for a project */
411
422
  async publish() {
412
423
  const { projectId } = this.options;
413
424
  const fetchUri = this.createUrl("/api/v1/publish", { siteId: projectId });
@@ -437,11 +448,13 @@ var _QuirkClient = class extends ApiClient {
437
448
  constructor(options) {
438
449
  super(options);
439
450
  }
451
+ /** Fetches all Quirks for a project */
440
452
  async get(options) {
441
453
  const { projectId } = this.options;
442
454
  const fetchUri = this.createUrl(__privateGet(_QuirkClient, _url5), { ...options, projectId });
443
455
  return await this.apiClient(fetchUri);
444
456
  }
457
+ /** Updates or creates (based on id) a Quirk */
445
458
  async upsert(body) {
446
459
  const fetchUri = this.createUrl(__privateGet(_QuirkClient, _url5));
447
460
  await this.apiClient(fetchUri, {
@@ -450,6 +463,7 @@ var _QuirkClient = class extends ApiClient {
450
463
  expectNoContent: true
451
464
  });
452
465
  }
466
+ /** Deletes a Quirk */
453
467
  async remove(body) {
454
468
  const fetchUri = this.createUrl(__privateGet(_QuirkClient, _url5));
455
469
  await this.apiClient(fetchUri, {
@@ -479,11 +493,13 @@ var _SignalClient = class extends ApiClient {
479
493
  constructor(options) {
480
494
  super(options);
481
495
  }
496
+ /** Fetches all Signals for a project */
482
497
  async get(options) {
483
498
  const { projectId } = this.options;
484
499
  const fetchUri = this.createUrl(__privateGet(_SignalClient, _url6), { ...options, projectId });
485
500
  return await this.apiClient(fetchUri);
486
501
  }
502
+ /** Updates or creates (based on id) a Signal */
487
503
  async upsert(body) {
488
504
  const fetchUri = this.createUrl(__privateGet(_SignalClient, _url6));
489
505
  await this.apiClient(fetchUri, {
@@ -492,6 +508,7 @@ var _SignalClient = class extends ApiClient {
492
508
  expectNoContent: true
493
509
  });
494
510
  }
511
+ /** Deletes a Signal */
495
512
  async remove(body) {
496
513
  const fetchUri = this.createUrl(__privateGet(_SignalClient, _url6));
497
514
  await this.apiClient(fetchUri, {
@@ -521,11 +538,13 @@ var _TestClient = class extends ApiClient {
521
538
  constructor(options) {
522
539
  super(options);
523
540
  }
541
+ /** Fetches all Tests for a project */
524
542
  async get(options) {
525
543
  const { projectId } = this.options;
526
544
  const fetchUri = this.createUrl(__privateGet(_TestClient, _url7), { ...options, projectId });
527
545
  return await this.apiClient(fetchUri);
528
546
  }
547
+ /** Updates or creates (based on id) a Test */
529
548
  async upsert(body) {
530
549
  const fetchUri = this.createUrl(__privateGet(_TestClient, _url7));
531
550
  await this.apiClient(fetchUri, {
@@ -534,6 +553,7 @@ var _TestClient = class extends ApiClient {
534
553
  expectNoContent: true
535
554
  });
536
555
  }
556
+ /** Deletes a Test */
537
557
  async remove(body) {
538
558
  const fetchUri = this.createUrl(__privateGet(_TestClient, _url7));
539
559
  await this.apiClient(fetchUri, {
package/dist/api/api.mjs CHANGED
@@ -186,11 +186,13 @@ var _AggregateClient = class extends ApiClient {
186
186
  constructor(options) {
187
187
  super(options);
188
188
  }
189
+ /** Fetches all aggregates for a project */
189
190
  async get(options) {
190
191
  const { projectId } = this.options;
191
192
  const fetchUri = this.createUrl(__privateGet(_AggregateClient, _url), { ...options, projectId });
192
193
  return await this.apiClient(fetchUri);
193
194
  }
195
+ /** Updates or creates (based on id) an Aggregate */
194
196
  async upsert(body) {
195
197
  const fetchUri = this.createUrl(__privateGet(_AggregateClient, _url));
196
198
  await this.apiClient(fetchUri, {
@@ -199,6 +201,7 @@ var _AggregateClient = class extends ApiClient {
199
201
  expectNoContent: true
200
202
  });
201
203
  }
204
+ /** Deletes an Aggregate */
202
205
  async remove(body) {
203
206
  const fetchUri = this.createUrl(__privateGet(_AggregateClient, _url));
204
207
  await this.apiClient(fetchUri, {
@@ -263,6 +266,7 @@ var _DimensionClient = class extends ApiClient {
263
266
  constructor(options) {
264
267
  super(options);
265
268
  }
269
+ /** Fetches the known score dimensions for a project */
266
270
  async get(options) {
267
271
  const { projectId } = this.options;
268
272
  const fetchUri = this.createUrl(__privateGet(_DimensionClient, _url2), { ...options, projectId });
@@ -289,11 +293,13 @@ var _EnrichmentClient = class extends ApiClient {
289
293
  constructor(options) {
290
294
  super(options);
291
295
  }
296
+ /** Fetches all enrichments and values for a project, grouped by category */
292
297
  async get(options) {
293
298
  const { projectId } = this.options;
294
299
  const fetchUri = this.createUrl(__privateGet(_EnrichmentClient, _url3), { ...options, projectId });
295
300
  return await this.apiClient(fetchUri);
296
301
  }
302
+ /** Updates or creates (based on id) an enrichment category */
297
303
  async upsertCategory(body) {
298
304
  const fetchUri = this.createUrl(__privateGet(_EnrichmentClient, _url3));
299
305
  await this.apiClient(fetchUri, {
@@ -302,6 +308,7 @@ var _EnrichmentClient = class extends ApiClient {
302
308
  expectNoContent: true
303
309
  });
304
310
  }
311
+ /** Deletes an enrichment category */
305
312
  async removeCategory(body) {
306
313
  const fetchUri = this.createUrl(__privateGet(_EnrichmentClient, _url3));
307
314
  await this.apiClient(fetchUri, {
@@ -310,6 +317,7 @@ var _EnrichmentClient = class extends ApiClient {
310
317
  expectNoContent: true
311
318
  });
312
319
  }
320
+ /** Updates or creates (based on id) an enrichment value within an enrichment category */
313
321
  async upsertValue(body) {
314
322
  const fetchUri = this.createUrl(__privateGet(_EnrichmentClient, _valueUrl));
315
323
  await this.apiClient(fetchUri, {
@@ -318,6 +326,7 @@ var _EnrichmentClient = class extends ApiClient {
318
326
  expectNoContent: true
319
327
  });
320
328
  }
329
+ /** Deletes an enrichment value within an enrichment category. The category is left alone. */
321
330
  async removeValue(body) {
322
331
  const fetchUri = this.createUrl(__privateGet(_EnrichmentClient, _valueUrl));
323
332
  await this.apiClient(fetchUri, {
@@ -349,11 +358,13 @@ var _ManifestClient = class extends ApiClient {
349
358
  constructor(options) {
350
359
  super(options);
351
360
  }
361
+ /** Fetches the Context manifest for a project */
352
362
  async get(options) {
353
363
  const { projectId } = this.options;
354
364
  const fetchUri = this.createUrl(__privateGet(_ManifestClient, _url4), { ...options, projectId });
355
365
  return await this.apiClient(fetchUri);
356
366
  }
367
+ /** Publishes the Context manifest for a project */
357
368
  async publish() {
358
369
  const { projectId } = this.options;
359
370
  const fetchUri = this.createUrl("/api/v1/publish", { siteId: projectId });
@@ -383,11 +394,13 @@ var _QuirkClient = class extends ApiClient {
383
394
  constructor(options) {
384
395
  super(options);
385
396
  }
397
+ /** Fetches all Quirks for a project */
386
398
  async get(options) {
387
399
  const { projectId } = this.options;
388
400
  const fetchUri = this.createUrl(__privateGet(_QuirkClient, _url5), { ...options, projectId });
389
401
  return await this.apiClient(fetchUri);
390
402
  }
403
+ /** Updates or creates (based on id) a Quirk */
391
404
  async upsert(body) {
392
405
  const fetchUri = this.createUrl(__privateGet(_QuirkClient, _url5));
393
406
  await this.apiClient(fetchUri, {
@@ -396,6 +409,7 @@ var _QuirkClient = class extends ApiClient {
396
409
  expectNoContent: true
397
410
  });
398
411
  }
412
+ /** Deletes a Quirk */
399
413
  async remove(body) {
400
414
  const fetchUri = this.createUrl(__privateGet(_QuirkClient, _url5));
401
415
  await this.apiClient(fetchUri, {
@@ -425,11 +439,13 @@ var _SignalClient = class extends ApiClient {
425
439
  constructor(options) {
426
440
  super(options);
427
441
  }
442
+ /** Fetches all Signals for a project */
428
443
  async get(options) {
429
444
  const { projectId } = this.options;
430
445
  const fetchUri = this.createUrl(__privateGet(_SignalClient, _url6), { ...options, projectId });
431
446
  return await this.apiClient(fetchUri);
432
447
  }
448
+ /** Updates or creates (based on id) a Signal */
433
449
  async upsert(body) {
434
450
  const fetchUri = this.createUrl(__privateGet(_SignalClient, _url6));
435
451
  await this.apiClient(fetchUri, {
@@ -438,6 +454,7 @@ var _SignalClient = class extends ApiClient {
438
454
  expectNoContent: true
439
455
  });
440
456
  }
457
+ /** Deletes a Signal */
441
458
  async remove(body) {
442
459
  const fetchUri = this.createUrl(__privateGet(_SignalClient, _url6));
443
460
  await this.apiClient(fetchUri, {
@@ -467,11 +484,13 @@ var _TestClient = class extends ApiClient {
467
484
  constructor(options) {
468
485
  super(options);
469
486
  }
487
+ /** Fetches all Tests for a project */
470
488
  async get(options) {
471
489
  const { projectId } = this.options;
472
490
  const fetchUri = this.createUrl(__privateGet(_TestClient, _url7), { ...options, projectId });
473
491
  return await this.apiClient(fetchUri);
474
492
  }
493
+ /** Updates or creates (based on id) a Test */
475
494
  async upsert(body) {
476
495
  const fetchUri = this.createUrl(__privateGet(_TestClient, _url7));
477
496
  await this.apiClient(fetchUri, {
@@ -480,6 +499,7 @@ var _TestClient = class extends ApiClient {
480
499
  expectNoContent: true
481
500
  });
482
501
  }
502
+ /** Deletes a Test */
483
503
  async remove(body) {
484
504
  const fetchUri = this.createUrl(__privateGet(_TestClient, _url7));
485
505
  await this.apiClient(fetchUri, {
package/dist/index.esm.js CHANGED
@@ -87,6 +87,7 @@ var SignalInstance = class {
87
87
  __privateSet(this, _evaluator, evaluator);
88
88
  __privateSet(this, _onLogMessage, onLogMessage);
89
89
  }
90
+ /** Computes storage update commands to take based on a state update and the signal's criteria */
90
91
  computeSignal(update, commands) {
91
92
  const isAtCap = update.scores[this.signal.id] >= this.signal.cap;
92
93
  if (isAtCap && this.signal.dur !== "t") {
@@ -128,6 +129,7 @@ var ManifestInstance = class {
128
129
  constructor({
129
130
  manifest,
130
131
  evaluator = new GroupCriteriaEvaluator({}),
132
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
131
133
  onLogMessage = () => {
132
134
  }
133
135
  }) {
@@ -168,6 +170,9 @@ var ManifestInstance = class {
168
170
  }
169
171
  return commands;
170
172
  }
173
+ /**
174
+ * Computes aggregated scores based on other dimensions
175
+ */
171
176
  computeAggregateDimensions(primitiveScores) {
172
177
  var _a, _b;
173
178
  return computeAggregateDimensions(primitiveScores, (_b = (_a = __privateGet(this, _mf).pz) == null ? void 0 : _a.agg) != null ? _b : {});
@@ -709,6 +714,9 @@ var TransitionDataStore = class {
709
714
  __privateAdd(this, _data, void 0);
710
715
  __privateAdd(this, _initialData, void 0);
711
716
  __privateAdd(this, _mitt, mitt());
717
+ /**
718
+ * Subscribe to events from the transition storage
719
+ */
712
720
  __publicField(this, "events", {
713
721
  on: __privateGet(this, _mitt).on,
714
722
  off: __privateGet(this, _mitt).off
@@ -724,10 +732,20 @@ var TransitionDataStore = class {
724
732
  get initialData() {
725
733
  return __privateGet(this, _initialData);
726
734
  }
735
+ /**
736
+ * Updates data in the transition storage.
737
+ * @param commands Commands to execute against existing stored value (event based stores)
738
+ * @param computedValue Pre-computed new value against existing value (object based stores)
739
+ * @returns Resolved promise when the data has been updated
740
+ */
727
741
  updateData(commands, computedValue) {
728
742
  __privateSet(this, _data, computedValue);
729
743
  return this.handleUpdateData(commands, computedValue);
730
744
  }
745
+ /**
746
+ * Deletes a visitor's stored data, forgetting them.
747
+ * @param fromAllDevices - false: logout from this device ID. true: forget all data about the visitor and their identity.
748
+ */
731
749
  async delete(fromAllDevices) {
732
750
  __privateSet(this, _data, void 0);
733
751
  await this.handleDelete(fromAllDevices);
@@ -739,6 +757,12 @@ var TransitionDataStore = class {
739
757
  __privateSet(this, _data, newScores);
740
758
  __privateGet(this, _mitt).emit("dataUpdatedAsync", newScores);
741
759
  }
760
+ /**
761
+ * When we load on the client side after a server side rendering has occurred (server to client transition),
762
+ * we can have a page script (ID: __UNIFORM_DATA__) that contains the computed visitor data from the SSR/edge render.
763
+ * This data is injected into the first render to allow score syncing and the server to request commands be applied
764
+ * to the client side data store.
765
+ */
742
766
  getClientTransitionState() {
743
767
  if (typeof document === "undefined") {
744
768
  return;
@@ -833,6 +857,7 @@ function parseScoreCookie(cookieValue) {
833
857
  return;
834
858
  const [abTestData, sessionScores, visitorScores] = types;
835
859
  return {
860
+ // this is true since we're reading a cookie, which wouldn't exist if consent wasn't given
836
861
  consent: true,
837
862
  sessionScores: decodeCookieType(parseCookieType(sessionScores)),
838
863
  scores: decodeCookieType(parseCookieType(visitorScores)),
@@ -1049,16 +1074,30 @@ var STORAGE_KEY = "ufvisitor";
1049
1074
  var _mitt2, _persist, _visitTimeout, _options, _currentData, currentData_get, _replaceData, replaceData_fn, _setVisitTimeout, setVisitTimeout_fn, _isExpired, isExpired_fn, _handleCaps, handleCaps_fn, _defaultData, defaultData_fn;
1050
1075
  var VisitorDataStore = class {
1051
1076
  constructor(options) {
1077
+ /** Gets the current client-side storage data. This property is always up to date. */
1052
1078
  __privateAdd(this, _currentData);
1079
+ /**
1080
+ * IMPORTANT: This function mutates the input data. This is done,
1081
+ * because all the sources that call it have either already spread or cloned
1082
+ * the data, so we can safely mutate it for better perf.
1083
+ */
1053
1084
  __privateAdd(this, _replaceData);
1054
1085
  __privateAdd(this, _setVisitTimeout);
1055
1086
  __privateAdd(this, _isExpired);
1087
+ /**
1088
+ * IMPORTANT: This function mutates the input data. This is done,
1089
+ * because all the sources that call it have either already spread or cloned
1090
+ * the data, so we can safely mutate it for better perf.
1091
+ */
1056
1092
  __privateAdd(this, _handleCaps);
1057
1093
  __privateAdd(this, _defaultData);
1058
1094
  __privateAdd(this, _mitt2, mitt2());
1059
1095
  __privateAdd(this, _persist, new LocalStorage());
1060
1096
  __privateAdd(this, _visitTimeout, void 0);
1061
1097
  __privateAdd(this, _options, void 0);
1098
+ /**
1099
+ * Subscribe to events from storage
1100
+ */
1062
1101
  __publicField(this, "events", {
1063
1102
  on: __privateGet(this, _mitt2).on,
1064
1103
  off: __privateGet(this, _mitt2).off
@@ -1080,10 +1119,16 @@ var VisitorDataStore = class {
1080
1119
  });
1081
1120
  const transitionData = options.transitionStore.data;
1082
1121
  if (transitionData) {
1083
- __privateMethod(this, _replaceData, replaceData_fn).call(this, { ...__privateGet(this, _currentData, currentData_get).visitorData, ...transitionData }, true);
1122
+ __privateMethod(this, _replaceData, replaceData_fn).call(
1123
+ this,
1124
+ // we know _currentData is not empty because we inited it above if it was
1125
+ { ...__privateGet(this, _currentData, currentData_get).visitorData, ...transitionData },
1126
+ true
1127
+ );
1084
1128
  }
1085
1129
  }
1086
1130
  }
1131
+ /** Gets the current visitor data. This property is always up to date. */
1087
1132
  get data() {
1088
1133
  var _a, _b;
1089
1134
  const data = __privateGet(this, _currentData, currentData_get);
@@ -1101,6 +1146,7 @@ var VisitorDataStore = class {
1101
1146
  get options() {
1102
1147
  return __privateGet(this, _options);
1103
1148
  }
1149
+ /** Push data update command(s) into the visitor data */
1104
1150
  async updateData(commands) {
1105
1151
  var _a, _b, _c, _d;
1106
1152
  if (commands.length === 0) {
@@ -1114,6 +1160,11 @@ var VisitorDataStore = class {
1114
1160
  __privateMethod(this, _replaceData, replaceData_fn).call(this, newData);
1115
1161
  await ((_d = __privateGet(this, _options).transitionStore) == null ? void 0 : _d.updateData(commands, __privateGet(this, _currentData, currentData_get).visitorData));
1116
1162
  }
1163
+ /**
1164
+ * Deletes visitor data (forgetting them)
1165
+ * In most cases you should use forget() on the Context instead of this function, which also clears the Context state.
1166
+ * @param fromAllDevices for an identified user, whether to delete all their data (for the entire account) - true, or data for this device (sign out) - false
1167
+ */
1117
1168
  async delete(fromAllDevices) {
1118
1169
  var _a, _b, _c, _d, _e;
1119
1170
  (_b = (_a = __privateGet(this, _options)).onLogMessage) == null ? void 0 : _b.call(_a, ["info", 103, "GROUP", fromAllDevices]);
@@ -1243,6 +1294,9 @@ var Context = class {
1243
1294
  __privateAdd(this, _state, void 0);
1244
1295
  __privateAdd(this, _pzCache, {});
1245
1296
  __privateAdd(this, _mitt3, mitt3());
1297
+ /**
1298
+ * Subscribe to events
1299
+ */
1246
1300
  __publicField(this, "events", {
1247
1301
  on: __privateGet(this, _mitt3).on,
1248
1302
  off: __privateGet(this, _mitt3).off
@@ -1308,13 +1362,24 @@ var Context = class {
1308
1362
  __privateGet(this, _mitt3).emit("log", ["info", 1, "ENDGROUP"]);
1309
1363
  }
1310
1364
  }
1365
+ /** Gets the current visitor's dimension score vector. */
1311
1366
  get scores() {
1312
1367
  return __privateGet(this, _scores);
1313
1368
  }
1369
+ /** Gets the current visitor's quirks values. */
1314
1370
  get quirks() {
1315
1371
  var _a, _b;
1316
1372
  return (_b = (_a = __privateGet(this, _serverTransitionState)) == null ? void 0 : _a.quirks) != null ? _b : this.storage.data.quirks;
1317
1373
  }
1374
+ /**
1375
+ * Updates the Context with new data of any sort, such as
1376
+ * new URLs, cookies, quirks, and enrichments.
1377
+ *
1378
+ * Only properties that are set in the data parameter will be updated.
1379
+ * Properties that do not result in a changed state,
1380
+ * i.e. pushing the same URL or cookies as before,
1381
+ * will NOT result in a recomputation of signal state.
1382
+ */
1318
1383
  async update(newData) {
1319
1384
  var _a, _b, _c;
1320
1385
  const commands = [];
@@ -1353,6 +1418,8 @@ var Context = class {
1353
1418
  "GROUP",
1354
1419
  {
1355
1420
  ...newData,
1421
+ // need to convert url to string so it can be json serialized
1422
+ // to go over postMessage to chrome extension
1356
1423
  url: (_c = newData.url) == null ? void 0 : _c.toString()
1357
1424
  }
1358
1425
  ]);
@@ -1386,6 +1453,9 @@ var Context = class {
1386
1453
  state: newData,
1387
1454
  previousState: __privateGet(this, _state),
1388
1455
  visitor: this.storage.data,
1456
+ // re-compute using scores from storage instead of the current scores since
1457
+ // server transition scores might have adjusted values already integrated into them,
1458
+ // which causes issues when you are near limits.
1389
1459
  scores: __privateGet(this, _serverTransitionState) ? __privateMethod(this, _calculateScores, calculateScores_fn).call(this, this.storage.data) : __privateGet(this, _scores)
1390
1460
  })
1391
1461
  );
@@ -1410,6 +1480,7 @@ var Context = class {
1410
1480
  __privateGet(this, _mitt3).emit("log", ["info", 2, "ENDGROUP"]);
1411
1481
  }
1412
1482
  }
1483
+ /** use test() instead */
1413
1484
  getTestVariantId(testName) {
1414
1485
  var _a, _b, _c, _d;
1415
1486
  const definition = this.manifest.getTest(testName);
@@ -1419,6 +1490,7 @@ var Context = class {
1419
1490
  }
1420
1491
  return (_d = (_c = definition.wv) != null ? _c : (_b = (_a = __privateGet(this, _serverTransitionState)) == null ? void 0 : _a.tests) == null ? void 0 : _b[testName]) != null ? _d : this.storage.data.tests[testName];
1421
1492
  }
1493
+ /** use test() instead */
1422
1494
  setTestVariantId(testName, variantId) {
1423
1495
  this.storage.updateData([
1424
1496
  {
@@ -1430,9 +1502,14 @@ var Context = class {
1430
1502
  }
1431
1503
  ]);
1432
1504
  }
1505
+ /**
1506
+ * Writes a message to the Context log sink.
1507
+ * Used by Uniform internal SDK; not intended for public use.
1508
+ */
1433
1509
  log(...message) {
1434
1510
  __privateGet(this, _mitt3).emit("log", message);
1435
1511
  }
1512
+ /** Executes an A/B test with a given set of variants, showing the visitor's assigned variant (or selecting one to assign, if none is set yet) */
1436
1513
  test(options) {
1437
1514
  var _a, _b;
1438
1515
  const value = testVariations({
@@ -1447,6 +1524,7 @@ var Context = class {
1447
1524
  });
1448
1525
  return value;
1449
1526
  }
1527
+ /** Executes a personalized placement with a given set of variants */
1450
1528
  personalize(options) {
1451
1529
  const value = personalizeVariations({
1452
1530
  ...options,
@@ -1470,10 +1548,19 @@ var Context = class {
1470
1548
  __privateGet(this, _pzCache)[options.name] = eventData.variantIds;
1471
1549
  return value;
1472
1550
  }
1551
+ /**
1552
+ * Forgets the visitor's data and resets the Context to its initial state.
1553
+ * @param fromAllDevices for an identified user, whether to delete all their data (for the entire account) - true, or data for this device (sign out) - false
1554
+ */
1473
1555
  async forget(fromAllDevices) {
1474
1556
  __privateSet(this, _state, {});
1475
1557
  await this.storage.delete(fromAllDevices);
1476
1558
  }
1559
+ /**
1560
+ * Computes server to client transition state.
1561
+ *
1562
+ * Removes state from server-to-client if it came in initial state (cookies) to avoid double tracking on the client.
1563
+ */
1477
1564
  getServerToClientTransitionState() {
1478
1565
  const transitionState = {
1479
1566
  quirks: this.storage.data.quirks,
@@ -1676,11 +1763,13 @@ import rfdc3 from "rfdc";
1676
1763
 
1677
1764
  // src/logging/messageContent.ts
1678
1765
  var messageContent = {
1766
+ // CONTEXT
1679
1767
  1: () => ["context", "initializing Uniform Context"],
1680
1768
  2: (update) => ["context", "received update()", update],
1681
1769
  3: (scores) => ["context", "new score vector", scores],
1682
1770
  4: (quirks) => ["context", "updated quirks", quirks],
1683
1771
  5: (enrichment) => ["context", "ignored enrichment update for unknown enrichment category", enrichment.cat],
1772
+ // STORAGE
1684
1773
  101: (commands) => ["storage", "received update commands", commands],
1685
1774
  102: (data) => ["storage", "data was updated", data],
1686
1775
  103: (fromAllDevices) => [
@@ -1700,6 +1789,7 @@ var messageContent = {
1700
1789
  ],
1701
1790
  131: () => ["storage", "server to client transition data was discarded"],
1702
1791
  140: (decayMessage) => ["storage", `score decay was applied: ${decayMessage}`],
1792
+ // SIGNAL EVAL
1703
1793
  200: () => ["signals", "evaluating signals"],
1704
1794
  201: (signal) => ["signals", `evaluating signal ${signal.id} (${signal.dur})`],
1705
1795
  202: (group) => ["signals", group.op === "|" ? "OR" : "AND"],
@@ -1711,10 +1801,12 @@ var messageContent = {
1711
1801
  "signals",
1712
1802
  `group result: ${result.result} [${result.changed ? "CHANGED" : "unchanged"}]`
1713
1803
  ],
1804
+ // PERSONALIZATION
1714
1805
  300: (placement) => ["personalization", `executing personalization '${placement.name}'`],
1715
1806
  301: ({ id, op }) => ["personalization", `testing variation ${id} (${op === "|" ? "OR" : "AND"})`],
1716
1807
  302: ({ matched, description }) => ["personalization", `${description} is ${matched}`],
1717
1808
  303: (selected) => ["personalization", selected ? "selected variation" : "did not select variation"],
1809
+ // TESTING
1718
1810
  400: (name) => ["testing", `executing A/B test '${name}'`],
1719
1811
  401: (testName) => ["testing", `${testName} is not registered in the manifest; it will not be run.`],
1720
1812
  402: ({ missingVariant, variants }) => [
@@ -1725,6 +1817,7 @@ var messageContent = {
1725
1817
  ],
1726
1818
  403: (variant) => ["testing", `assigned new test variant '${variant}'`],
1727
1819
  404: (variant) => ["testing", `displaying variation '${variant}'`],
1820
+ // GTAG
1728
1821
  700: () => [
1729
1822
  "gtag",
1730
1823
  "gtag is not defined, skipping analytics event emission. Ensure you have added the gtag script to your page."
package/dist/index.js CHANGED
@@ -19,6 +19,10 @@ var __copyProps = (to, from, except, desc) => {
19
19
  return to;
20
20
  };
21
21
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
26
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
27
  mod
24
28
  ));
@@ -151,6 +155,7 @@ var SignalInstance = class {
151
155
  __privateSet(this, _evaluator, evaluator);
152
156
  __privateSet(this, _onLogMessage, onLogMessage);
153
157
  }
158
+ /** Computes storage update commands to take based on a state update and the signal's criteria */
154
159
  computeSignal(update, commands) {
155
160
  const isAtCap = update.scores[this.signal.id] >= this.signal.cap;
156
161
  if (isAtCap && this.signal.dur !== "t") {
@@ -192,6 +197,7 @@ var ManifestInstance = class {
192
197
  constructor({
193
198
  manifest,
194
199
  evaluator = new GroupCriteriaEvaluator({}),
200
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
195
201
  onLogMessage = () => {
196
202
  }
197
203
  }) {
@@ -232,6 +238,9 @@ var ManifestInstance = class {
232
238
  }
233
239
  return commands;
234
240
  }
241
+ /**
242
+ * Computes aggregated scores based on other dimensions
243
+ */
235
244
  computeAggregateDimensions(primitiveScores) {
236
245
  var _a, _b;
237
246
  return computeAggregateDimensions(primitiveScores, (_b = (_a = __privateGet(this, _mf).pz) == null ? void 0 : _a.agg) != null ? _b : {});
@@ -773,6 +782,9 @@ var TransitionDataStore = class {
773
782
  __privateAdd(this, _data, void 0);
774
783
  __privateAdd(this, _initialData, void 0);
775
784
  __privateAdd(this, _mitt, (0, import_mitt.default)());
785
+ /**
786
+ * Subscribe to events from the transition storage
787
+ */
776
788
  __publicField(this, "events", {
777
789
  on: __privateGet(this, _mitt).on,
778
790
  off: __privateGet(this, _mitt).off
@@ -788,10 +800,20 @@ var TransitionDataStore = class {
788
800
  get initialData() {
789
801
  return __privateGet(this, _initialData);
790
802
  }
803
+ /**
804
+ * Updates data in the transition storage.
805
+ * @param commands Commands to execute against existing stored value (event based stores)
806
+ * @param computedValue Pre-computed new value against existing value (object based stores)
807
+ * @returns Resolved promise when the data has been updated
808
+ */
791
809
  updateData(commands, computedValue) {
792
810
  __privateSet(this, _data, computedValue);
793
811
  return this.handleUpdateData(commands, computedValue);
794
812
  }
813
+ /**
814
+ * Deletes a visitor's stored data, forgetting them.
815
+ * @param fromAllDevices - false: logout from this device ID. true: forget all data about the visitor and their identity.
816
+ */
795
817
  async delete(fromAllDevices) {
796
818
  __privateSet(this, _data, void 0);
797
819
  await this.handleDelete(fromAllDevices);
@@ -803,6 +825,12 @@ var TransitionDataStore = class {
803
825
  __privateSet(this, _data, newScores);
804
826
  __privateGet(this, _mitt).emit("dataUpdatedAsync", newScores);
805
827
  }
828
+ /**
829
+ * When we load on the client side after a server side rendering has occurred (server to client transition),
830
+ * we can have a page script (ID: __UNIFORM_DATA__) that contains the computed visitor data from the SSR/edge render.
831
+ * This data is injected into the first render to allow score syncing and the server to request commands be applied
832
+ * to the client side data store.
833
+ */
806
834
  getClientTransitionState() {
807
835
  if (typeof document === "undefined") {
808
836
  return;
@@ -897,6 +925,7 @@ function parseScoreCookie(cookieValue) {
897
925
  return;
898
926
  const [abTestData, sessionScores, visitorScores] = types;
899
927
  return {
928
+ // this is true since we're reading a cookie, which wouldn't exist if consent wasn't given
900
929
  consent: true,
901
930
  sessionScores: decodeCookieType(parseCookieType(sessionScores)),
902
931
  scores: decodeCookieType(parseCookieType(visitorScores)),
@@ -1113,16 +1142,30 @@ var STORAGE_KEY = "ufvisitor";
1113
1142
  var _mitt2, _persist, _visitTimeout, _options, _currentData, currentData_get, _replaceData, replaceData_fn, _setVisitTimeout, setVisitTimeout_fn, _isExpired, isExpired_fn, _handleCaps, handleCaps_fn, _defaultData, defaultData_fn;
1114
1143
  var VisitorDataStore = class {
1115
1144
  constructor(options) {
1145
+ /** Gets the current client-side storage data. This property is always up to date. */
1116
1146
  __privateAdd(this, _currentData);
1147
+ /**
1148
+ * IMPORTANT: This function mutates the input data. This is done,
1149
+ * because all the sources that call it have either already spread or cloned
1150
+ * the data, so we can safely mutate it for better perf.
1151
+ */
1117
1152
  __privateAdd(this, _replaceData);
1118
1153
  __privateAdd(this, _setVisitTimeout);
1119
1154
  __privateAdd(this, _isExpired);
1155
+ /**
1156
+ * IMPORTANT: This function mutates the input data. This is done,
1157
+ * because all the sources that call it have either already spread or cloned
1158
+ * the data, so we can safely mutate it for better perf.
1159
+ */
1120
1160
  __privateAdd(this, _handleCaps);
1121
1161
  __privateAdd(this, _defaultData);
1122
1162
  __privateAdd(this, _mitt2, (0, import_mitt2.default)());
1123
1163
  __privateAdd(this, _persist, new LocalStorage());
1124
1164
  __privateAdd(this, _visitTimeout, void 0);
1125
1165
  __privateAdd(this, _options, void 0);
1166
+ /**
1167
+ * Subscribe to events from storage
1168
+ */
1126
1169
  __publicField(this, "events", {
1127
1170
  on: __privateGet(this, _mitt2).on,
1128
1171
  off: __privateGet(this, _mitt2).off
@@ -1144,10 +1187,16 @@ var VisitorDataStore = class {
1144
1187
  });
1145
1188
  const transitionData = options.transitionStore.data;
1146
1189
  if (transitionData) {
1147
- __privateMethod(this, _replaceData, replaceData_fn).call(this, { ...__privateGet(this, _currentData, currentData_get).visitorData, ...transitionData }, true);
1190
+ __privateMethod(this, _replaceData, replaceData_fn).call(
1191
+ this,
1192
+ // we know _currentData is not empty because we inited it above if it was
1193
+ { ...__privateGet(this, _currentData, currentData_get).visitorData, ...transitionData },
1194
+ true
1195
+ );
1148
1196
  }
1149
1197
  }
1150
1198
  }
1199
+ /** Gets the current visitor data. This property is always up to date. */
1151
1200
  get data() {
1152
1201
  var _a, _b;
1153
1202
  const data = __privateGet(this, _currentData, currentData_get);
@@ -1165,6 +1214,7 @@ var VisitorDataStore = class {
1165
1214
  get options() {
1166
1215
  return __privateGet(this, _options);
1167
1216
  }
1217
+ /** Push data update command(s) into the visitor data */
1168
1218
  async updateData(commands) {
1169
1219
  var _a, _b, _c, _d;
1170
1220
  if (commands.length === 0) {
@@ -1178,6 +1228,11 @@ var VisitorDataStore = class {
1178
1228
  __privateMethod(this, _replaceData, replaceData_fn).call(this, newData);
1179
1229
  await ((_d = __privateGet(this, _options).transitionStore) == null ? void 0 : _d.updateData(commands, __privateGet(this, _currentData, currentData_get).visitorData));
1180
1230
  }
1231
+ /**
1232
+ * Deletes visitor data (forgetting them)
1233
+ * In most cases you should use forget() on the Context instead of this function, which also clears the Context state.
1234
+ * @param fromAllDevices for an identified user, whether to delete all their data (for the entire account) - true, or data for this device (sign out) - false
1235
+ */
1181
1236
  async delete(fromAllDevices) {
1182
1237
  var _a, _b, _c, _d, _e;
1183
1238
  (_b = (_a = __privateGet(this, _options)).onLogMessage) == null ? void 0 : _b.call(_a, ["info", 103, "GROUP", fromAllDevices]);
@@ -1307,6 +1362,9 @@ var Context = class {
1307
1362
  __privateAdd(this, _state, void 0);
1308
1363
  __privateAdd(this, _pzCache, {});
1309
1364
  __privateAdd(this, _mitt3, (0, import_mitt3.default)());
1365
+ /**
1366
+ * Subscribe to events
1367
+ */
1310
1368
  __publicField(this, "events", {
1311
1369
  on: __privateGet(this, _mitt3).on,
1312
1370
  off: __privateGet(this, _mitt3).off
@@ -1372,13 +1430,24 @@ var Context = class {
1372
1430
  __privateGet(this, _mitt3).emit("log", ["info", 1, "ENDGROUP"]);
1373
1431
  }
1374
1432
  }
1433
+ /** Gets the current visitor's dimension score vector. */
1375
1434
  get scores() {
1376
1435
  return __privateGet(this, _scores);
1377
1436
  }
1437
+ /** Gets the current visitor's quirks values. */
1378
1438
  get quirks() {
1379
1439
  var _a, _b;
1380
1440
  return (_b = (_a = __privateGet(this, _serverTransitionState)) == null ? void 0 : _a.quirks) != null ? _b : this.storage.data.quirks;
1381
1441
  }
1442
+ /**
1443
+ * Updates the Context with new data of any sort, such as
1444
+ * new URLs, cookies, quirks, and enrichments.
1445
+ *
1446
+ * Only properties that are set in the data parameter will be updated.
1447
+ * Properties that do not result in a changed state,
1448
+ * i.e. pushing the same URL or cookies as before,
1449
+ * will NOT result in a recomputation of signal state.
1450
+ */
1382
1451
  async update(newData) {
1383
1452
  var _a, _b, _c;
1384
1453
  const commands = [];
@@ -1417,6 +1486,8 @@ var Context = class {
1417
1486
  "GROUP",
1418
1487
  {
1419
1488
  ...newData,
1489
+ // need to convert url to string so it can be json serialized
1490
+ // to go over postMessage to chrome extension
1420
1491
  url: (_c = newData.url) == null ? void 0 : _c.toString()
1421
1492
  }
1422
1493
  ]);
@@ -1450,6 +1521,9 @@ var Context = class {
1450
1521
  state: newData,
1451
1522
  previousState: __privateGet(this, _state),
1452
1523
  visitor: this.storage.data,
1524
+ // re-compute using scores from storage instead of the current scores since
1525
+ // server transition scores might have adjusted values already integrated into them,
1526
+ // which causes issues when you are near limits.
1453
1527
  scores: __privateGet(this, _serverTransitionState) ? __privateMethod(this, _calculateScores, calculateScores_fn).call(this, this.storage.data) : __privateGet(this, _scores)
1454
1528
  })
1455
1529
  );
@@ -1474,6 +1548,7 @@ var Context = class {
1474
1548
  __privateGet(this, _mitt3).emit("log", ["info", 2, "ENDGROUP"]);
1475
1549
  }
1476
1550
  }
1551
+ /** use test() instead */
1477
1552
  getTestVariantId(testName) {
1478
1553
  var _a, _b, _c, _d;
1479
1554
  const definition = this.manifest.getTest(testName);
@@ -1483,6 +1558,7 @@ var Context = class {
1483
1558
  }
1484
1559
  return (_d = (_c = definition.wv) != null ? _c : (_b = (_a = __privateGet(this, _serverTransitionState)) == null ? void 0 : _a.tests) == null ? void 0 : _b[testName]) != null ? _d : this.storage.data.tests[testName];
1485
1560
  }
1561
+ /** use test() instead */
1486
1562
  setTestVariantId(testName, variantId) {
1487
1563
  this.storage.updateData([
1488
1564
  {
@@ -1494,9 +1570,14 @@ var Context = class {
1494
1570
  }
1495
1571
  ]);
1496
1572
  }
1573
+ /**
1574
+ * Writes a message to the Context log sink.
1575
+ * Used by Uniform internal SDK; not intended for public use.
1576
+ */
1497
1577
  log(...message) {
1498
1578
  __privateGet(this, _mitt3).emit("log", message);
1499
1579
  }
1580
+ /** Executes an A/B test with a given set of variants, showing the visitor's assigned variant (or selecting one to assign, if none is set yet) */
1500
1581
  test(options) {
1501
1582
  var _a, _b;
1502
1583
  const value = testVariations({
@@ -1511,6 +1592,7 @@ var Context = class {
1511
1592
  });
1512
1593
  return value;
1513
1594
  }
1595
+ /** Executes a personalized placement with a given set of variants */
1514
1596
  personalize(options) {
1515
1597
  const value = personalizeVariations({
1516
1598
  ...options,
@@ -1534,10 +1616,19 @@ var Context = class {
1534
1616
  __privateGet(this, _pzCache)[options.name] = eventData.variantIds;
1535
1617
  return value;
1536
1618
  }
1619
+ /**
1620
+ * Forgets the visitor's data and resets the Context to its initial state.
1621
+ * @param fromAllDevices for an identified user, whether to delete all their data (for the entire account) - true, or data for this device (sign out) - false
1622
+ */
1537
1623
  async forget(fromAllDevices) {
1538
1624
  __privateSet(this, _state, {});
1539
1625
  await this.storage.delete(fromAllDevices);
1540
1626
  }
1627
+ /**
1628
+ * Computes server to client transition state.
1629
+ *
1630
+ * Removes state from server-to-client if it came in initial state (cookies) to avoid double tracking on the client.
1631
+ */
1541
1632
  getServerToClientTransitionState() {
1542
1633
  const transitionState = {
1543
1634
  quirks: this.storage.data.quirks,
@@ -1740,11 +1831,13 @@ var import_rfdc3 = __toESM(require("rfdc"));
1740
1831
 
1741
1832
  // src/logging/messageContent.ts
1742
1833
  var messageContent = {
1834
+ // CONTEXT
1743
1835
  1: () => ["context", "initializing Uniform Context"],
1744
1836
  2: (update) => ["context", "received update()", update],
1745
1837
  3: (scores) => ["context", "new score vector", scores],
1746
1838
  4: (quirks) => ["context", "updated quirks", quirks],
1747
1839
  5: (enrichment) => ["context", "ignored enrichment update for unknown enrichment category", enrichment.cat],
1840
+ // STORAGE
1748
1841
  101: (commands) => ["storage", "received update commands", commands],
1749
1842
  102: (data) => ["storage", "data was updated", data],
1750
1843
  103: (fromAllDevices) => [
@@ -1764,6 +1857,7 @@ var messageContent = {
1764
1857
  ],
1765
1858
  131: () => ["storage", "server to client transition data was discarded"],
1766
1859
  140: (decayMessage) => ["storage", `score decay was applied: ${decayMessage}`],
1860
+ // SIGNAL EVAL
1767
1861
  200: () => ["signals", "evaluating signals"],
1768
1862
  201: (signal) => ["signals", `evaluating signal ${signal.id} (${signal.dur})`],
1769
1863
  202: (group) => ["signals", group.op === "|" ? "OR" : "AND"],
@@ -1775,10 +1869,12 @@ var messageContent = {
1775
1869
  "signals",
1776
1870
  `group result: ${result.result} [${result.changed ? "CHANGED" : "unchanged"}]`
1777
1871
  ],
1872
+ // PERSONALIZATION
1778
1873
  300: (placement) => ["personalization", `executing personalization '${placement.name}'`],
1779
1874
  301: ({ id, op }) => ["personalization", `testing variation ${id} (${op === "|" ? "OR" : "AND"})`],
1780
1875
  302: ({ matched, description }) => ["personalization", `${description} is ${matched}`],
1781
1876
  303: (selected) => ["personalization", selected ? "selected variation" : "did not select variation"],
1877
+ // TESTING
1782
1878
  400: (name) => ["testing", `executing A/B test '${name}'`],
1783
1879
  401: (testName) => ["testing", `${testName} is not registered in the manifest; it will not be run.`],
1784
1880
  402: ({ missingVariant, variants }) => [
@@ -1789,6 +1885,7 @@ var messageContent = {
1789
1885
  ],
1790
1886
  403: (variant) => ["testing", `assigned new test variant '${variant}'`],
1791
1887
  404: (variant) => ["testing", `displaying variation '${variant}'`],
1888
+ // GTAG
1792
1889
  700: () => [
1793
1890
  "gtag",
1794
1891
  "gtag is not defined, skipping analytics event emission. Ensure you have added the gtag script to your page."
package/dist/index.mjs CHANGED
@@ -87,6 +87,7 @@ var SignalInstance = class {
87
87
  __privateSet(this, _evaluator, evaluator);
88
88
  __privateSet(this, _onLogMessage, onLogMessage);
89
89
  }
90
+ /** Computes storage update commands to take based on a state update and the signal's criteria */
90
91
  computeSignal(update, commands) {
91
92
  const isAtCap = update.scores[this.signal.id] >= this.signal.cap;
92
93
  if (isAtCap && this.signal.dur !== "t") {
@@ -128,6 +129,7 @@ var ManifestInstance = class {
128
129
  constructor({
129
130
  manifest,
130
131
  evaluator = new GroupCriteriaEvaluator({}),
132
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
131
133
  onLogMessage = () => {
132
134
  }
133
135
  }) {
@@ -168,6 +170,9 @@ var ManifestInstance = class {
168
170
  }
169
171
  return commands;
170
172
  }
173
+ /**
174
+ * Computes aggregated scores based on other dimensions
175
+ */
171
176
  computeAggregateDimensions(primitiveScores) {
172
177
  var _a, _b;
173
178
  return computeAggregateDimensions(primitiveScores, (_b = (_a = __privateGet(this, _mf).pz) == null ? void 0 : _a.agg) != null ? _b : {});
@@ -709,6 +714,9 @@ var TransitionDataStore = class {
709
714
  __privateAdd(this, _data, void 0);
710
715
  __privateAdd(this, _initialData, void 0);
711
716
  __privateAdd(this, _mitt, mitt());
717
+ /**
718
+ * Subscribe to events from the transition storage
719
+ */
712
720
  __publicField(this, "events", {
713
721
  on: __privateGet(this, _mitt).on,
714
722
  off: __privateGet(this, _mitt).off
@@ -724,10 +732,20 @@ var TransitionDataStore = class {
724
732
  get initialData() {
725
733
  return __privateGet(this, _initialData);
726
734
  }
735
+ /**
736
+ * Updates data in the transition storage.
737
+ * @param commands Commands to execute against existing stored value (event based stores)
738
+ * @param computedValue Pre-computed new value against existing value (object based stores)
739
+ * @returns Resolved promise when the data has been updated
740
+ */
727
741
  updateData(commands, computedValue) {
728
742
  __privateSet(this, _data, computedValue);
729
743
  return this.handleUpdateData(commands, computedValue);
730
744
  }
745
+ /**
746
+ * Deletes a visitor's stored data, forgetting them.
747
+ * @param fromAllDevices - false: logout from this device ID. true: forget all data about the visitor and their identity.
748
+ */
731
749
  async delete(fromAllDevices) {
732
750
  __privateSet(this, _data, void 0);
733
751
  await this.handleDelete(fromAllDevices);
@@ -739,6 +757,12 @@ var TransitionDataStore = class {
739
757
  __privateSet(this, _data, newScores);
740
758
  __privateGet(this, _mitt).emit("dataUpdatedAsync", newScores);
741
759
  }
760
+ /**
761
+ * When we load on the client side after a server side rendering has occurred (server to client transition),
762
+ * we can have a page script (ID: __UNIFORM_DATA__) that contains the computed visitor data from the SSR/edge render.
763
+ * This data is injected into the first render to allow score syncing and the server to request commands be applied
764
+ * to the client side data store.
765
+ */
742
766
  getClientTransitionState() {
743
767
  if (typeof document === "undefined") {
744
768
  return;
@@ -833,6 +857,7 @@ function parseScoreCookie(cookieValue) {
833
857
  return;
834
858
  const [abTestData, sessionScores, visitorScores] = types;
835
859
  return {
860
+ // this is true since we're reading a cookie, which wouldn't exist if consent wasn't given
836
861
  consent: true,
837
862
  sessionScores: decodeCookieType(parseCookieType(sessionScores)),
838
863
  scores: decodeCookieType(parseCookieType(visitorScores)),
@@ -1049,16 +1074,30 @@ var STORAGE_KEY = "ufvisitor";
1049
1074
  var _mitt2, _persist, _visitTimeout, _options, _currentData, currentData_get, _replaceData, replaceData_fn, _setVisitTimeout, setVisitTimeout_fn, _isExpired, isExpired_fn, _handleCaps, handleCaps_fn, _defaultData, defaultData_fn;
1050
1075
  var VisitorDataStore = class {
1051
1076
  constructor(options) {
1077
+ /** Gets the current client-side storage data. This property is always up to date. */
1052
1078
  __privateAdd(this, _currentData);
1079
+ /**
1080
+ * IMPORTANT: This function mutates the input data. This is done,
1081
+ * because all the sources that call it have either already spread or cloned
1082
+ * the data, so we can safely mutate it for better perf.
1083
+ */
1053
1084
  __privateAdd(this, _replaceData);
1054
1085
  __privateAdd(this, _setVisitTimeout);
1055
1086
  __privateAdd(this, _isExpired);
1087
+ /**
1088
+ * IMPORTANT: This function mutates the input data. This is done,
1089
+ * because all the sources that call it have either already spread or cloned
1090
+ * the data, so we can safely mutate it for better perf.
1091
+ */
1056
1092
  __privateAdd(this, _handleCaps);
1057
1093
  __privateAdd(this, _defaultData);
1058
1094
  __privateAdd(this, _mitt2, mitt2());
1059
1095
  __privateAdd(this, _persist, new LocalStorage());
1060
1096
  __privateAdd(this, _visitTimeout, void 0);
1061
1097
  __privateAdd(this, _options, void 0);
1098
+ /**
1099
+ * Subscribe to events from storage
1100
+ */
1062
1101
  __publicField(this, "events", {
1063
1102
  on: __privateGet(this, _mitt2).on,
1064
1103
  off: __privateGet(this, _mitt2).off
@@ -1080,10 +1119,16 @@ var VisitorDataStore = class {
1080
1119
  });
1081
1120
  const transitionData = options.transitionStore.data;
1082
1121
  if (transitionData) {
1083
- __privateMethod(this, _replaceData, replaceData_fn).call(this, { ...__privateGet(this, _currentData, currentData_get).visitorData, ...transitionData }, true);
1122
+ __privateMethod(this, _replaceData, replaceData_fn).call(
1123
+ this,
1124
+ // we know _currentData is not empty because we inited it above if it was
1125
+ { ...__privateGet(this, _currentData, currentData_get).visitorData, ...transitionData },
1126
+ true
1127
+ );
1084
1128
  }
1085
1129
  }
1086
1130
  }
1131
+ /** Gets the current visitor data. This property is always up to date. */
1087
1132
  get data() {
1088
1133
  var _a, _b;
1089
1134
  const data = __privateGet(this, _currentData, currentData_get);
@@ -1101,6 +1146,7 @@ var VisitorDataStore = class {
1101
1146
  get options() {
1102
1147
  return __privateGet(this, _options);
1103
1148
  }
1149
+ /** Push data update command(s) into the visitor data */
1104
1150
  async updateData(commands) {
1105
1151
  var _a, _b, _c, _d;
1106
1152
  if (commands.length === 0) {
@@ -1114,6 +1160,11 @@ var VisitorDataStore = class {
1114
1160
  __privateMethod(this, _replaceData, replaceData_fn).call(this, newData);
1115
1161
  await ((_d = __privateGet(this, _options).transitionStore) == null ? void 0 : _d.updateData(commands, __privateGet(this, _currentData, currentData_get).visitorData));
1116
1162
  }
1163
+ /**
1164
+ * Deletes visitor data (forgetting them)
1165
+ * In most cases you should use forget() on the Context instead of this function, which also clears the Context state.
1166
+ * @param fromAllDevices for an identified user, whether to delete all their data (for the entire account) - true, or data for this device (sign out) - false
1167
+ */
1117
1168
  async delete(fromAllDevices) {
1118
1169
  var _a, _b, _c, _d, _e;
1119
1170
  (_b = (_a = __privateGet(this, _options)).onLogMessage) == null ? void 0 : _b.call(_a, ["info", 103, "GROUP", fromAllDevices]);
@@ -1243,6 +1294,9 @@ var Context = class {
1243
1294
  __privateAdd(this, _state, void 0);
1244
1295
  __privateAdd(this, _pzCache, {});
1245
1296
  __privateAdd(this, _mitt3, mitt3());
1297
+ /**
1298
+ * Subscribe to events
1299
+ */
1246
1300
  __publicField(this, "events", {
1247
1301
  on: __privateGet(this, _mitt3).on,
1248
1302
  off: __privateGet(this, _mitt3).off
@@ -1308,13 +1362,24 @@ var Context = class {
1308
1362
  __privateGet(this, _mitt3).emit("log", ["info", 1, "ENDGROUP"]);
1309
1363
  }
1310
1364
  }
1365
+ /** Gets the current visitor's dimension score vector. */
1311
1366
  get scores() {
1312
1367
  return __privateGet(this, _scores);
1313
1368
  }
1369
+ /** Gets the current visitor's quirks values. */
1314
1370
  get quirks() {
1315
1371
  var _a, _b;
1316
1372
  return (_b = (_a = __privateGet(this, _serverTransitionState)) == null ? void 0 : _a.quirks) != null ? _b : this.storage.data.quirks;
1317
1373
  }
1374
+ /**
1375
+ * Updates the Context with new data of any sort, such as
1376
+ * new URLs, cookies, quirks, and enrichments.
1377
+ *
1378
+ * Only properties that are set in the data parameter will be updated.
1379
+ * Properties that do not result in a changed state,
1380
+ * i.e. pushing the same URL or cookies as before,
1381
+ * will NOT result in a recomputation of signal state.
1382
+ */
1318
1383
  async update(newData) {
1319
1384
  var _a, _b, _c;
1320
1385
  const commands = [];
@@ -1353,6 +1418,8 @@ var Context = class {
1353
1418
  "GROUP",
1354
1419
  {
1355
1420
  ...newData,
1421
+ // need to convert url to string so it can be json serialized
1422
+ // to go over postMessage to chrome extension
1356
1423
  url: (_c = newData.url) == null ? void 0 : _c.toString()
1357
1424
  }
1358
1425
  ]);
@@ -1386,6 +1453,9 @@ var Context = class {
1386
1453
  state: newData,
1387
1454
  previousState: __privateGet(this, _state),
1388
1455
  visitor: this.storage.data,
1456
+ // re-compute using scores from storage instead of the current scores since
1457
+ // server transition scores might have adjusted values already integrated into them,
1458
+ // which causes issues when you are near limits.
1389
1459
  scores: __privateGet(this, _serverTransitionState) ? __privateMethod(this, _calculateScores, calculateScores_fn).call(this, this.storage.data) : __privateGet(this, _scores)
1390
1460
  })
1391
1461
  );
@@ -1410,6 +1480,7 @@ var Context = class {
1410
1480
  __privateGet(this, _mitt3).emit("log", ["info", 2, "ENDGROUP"]);
1411
1481
  }
1412
1482
  }
1483
+ /** use test() instead */
1413
1484
  getTestVariantId(testName) {
1414
1485
  var _a, _b, _c, _d;
1415
1486
  const definition = this.manifest.getTest(testName);
@@ -1419,6 +1490,7 @@ var Context = class {
1419
1490
  }
1420
1491
  return (_d = (_c = definition.wv) != null ? _c : (_b = (_a = __privateGet(this, _serverTransitionState)) == null ? void 0 : _a.tests) == null ? void 0 : _b[testName]) != null ? _d : this.storage.data.tests[testName];
1421
1492
  }
1493
+ /** use test() instead */
1422
1494
  setTestVariantId(testName, variantId) {
1423
1495
  this.storage.updateData([
1424
1496
  {
@@ -1430,9 +1502,14 @@ var Context = class {
1430
1502
  }
1431
1503
  ]);
1432
1504
  }
1505
+ /**
1506
+ * Writes a message to the Context log sink.
1507
+ * Used by Uniform internal SDK; not intended for public use.
1508
+ */
1433
1509
  log(...message) {
1434
1510
  __privateGet(this, _mitt3).emit("log", message);
1435
1511
  }
1512
+ /** Executes an A/B test with a given set of variants, showing the visitor's assigned variant (or selecting one to assign, if none is set yet) */
1436
1513
  test(options) {
1437
1514
  var _a, _b;
1438
1515
  const value = testVariations({
@@ -1447,6 +1524,7 @@ var Context = class {
1447
1524
  });
1448
1525
  return value;
1449
1526
  }
1527
+ /** Executes a personalized placement with a given set of variants */
1450
1528
  personalize(options) {
1451
1529
  const value = personalizeVariations({
1452
1530
  ...options,
@@ -1470,10 +1548,19 @@ var Context = class {
1470
1548
  __privateGet(this, _pzCache)[options.name] = eventData.variantIds;
1471
1549
  return value;
1472
1550
  }
1551
+ /**
1552
+ * Forgets the visitor's data and resets the Context to its initial state.
1553
+ * @param fromAllDevices for an identified user, whether to delete all their data (for the entire account) - true, or data for this device (sign out) - false
1554
+ */
1473
1555
  async forget(fromAllDevices) {
1474
1556
  __privateSet(this, _state, {});
1475
1557
  await this.storage.delete(fromAllDevices);
1476
1558
  }
1559
+ /**
1560
+ * Computes server to client transition state.
1561
+ *
1562
+ * Removes state from server-to-client if it came in initial state (cookies) to avoid double tracking on the client.
1563
+ */
1477
1564
  getServerToClientTransitionState() {
1478
1565
  const transitionState = {
1479
1566
  quirks: this.storage.data.quirks,
@@ -1676,11 +1763,13 @@ import rfdc3 from "rfdc";
1676
1763
 
1677
1764
  // src/logging/messageContent.ts
1678
1765
  var messageContent = {
1766
+ // CONTEXT
1679
1767
  1: () => ["context", "initializing Uniform Context"],
1680
1768
  2: (update) => ["context", "received update()", update],
1681
1769
  3: (scores) => ["context", "new score vector", scores],
1682
1770
  4: (quirks) => ["context", "updated quirks", quirks],
1683
1771
  5: (enrichment) => ["context", "ignored enrichment update for unknown enrichment category", enrichment.cat],
1772
+ // STORAGE
1684
1773
  101: (commands) => ["storage", "received update commands", commands],
1685
1774
  102: (data) => ["storage", "data was updated", data],
1686
1775
  103: (fromAllDevices) => [
@@ -1700,6 +1789,7 @@ var messageContent = {
1700
1789
  ],
1701
1790
  131: () => ["storage", "server to client transition data was discarded"],
1702
1791
  140: (decayMessage) => ["storage", `score decay was applied: ${decayMessage}`],
1792
+ // SIGNAL EVAL
1703
1793
  200: () => ["signals", "evaluating signals"],
1704
1794
  201: (signal) => ["signals", `evaluating signal ${signal.id} (${signal.dur})`],
1705
1795
  202: (group) => ["signals", group.op === "|" ? "OR" : "AND"],
@@ -1711,10 +1801,12 @@ var messageContent = {
1711
1801
  "signals",
1712
1802
  `group result: ${result.result} [${result.changed ? "CHANGED" : "unchanged"}]`
1713
1803
  ],
1804
+ // PERSONALIZATION
1714
1805
  300: (placement) => ["personalization", `executing personalization '${placement.name}'`],
1715
1806
  301: ({ id, op }) => ["personalization", `testing variation ${id} (${op === "|" ? "OR" : "AND"})`],
1716
1807
  302: ({ matched, description }) => ["personalization", `${description} is ${matched}`],
1717
1808
  303: (selected) => ["personalization", selected ? "selected variation" : "did not select variation"],
1809
+ // TESTING
1718
1810
  400: (name) => ["testing", `executing A/B test '${name}'`],
1719
1811
  401: (testName) => ["testing", `${testName} is not registered in the manifest; it will not be run.`],
1720
1812
  402: ({ missingVariant, variants }) => [
@@ -1725,6 +1817,7 @@ var messageContent = {
1725
1817
  ],
1726
1818
  403: (variant) => ["testing", `assigned new test variant '${variant}'`],
1727
1819
  404: (variant) => ["testing", `displaying variation '${variant}'`],
1820
+ // GTAG
1728
1821
  700: () => [
1729
1822
  "gtag",
1730
1823
  "gtag is not defined, skipping analytics event emission. Ensure you have added the gtag script to your page."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/context",
3
- "version": "18.17.1-alpha.13+77f2eaabc",
3
+ "version": "18.19.0",
4
4
  "description": "Uniform Context core package",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "main": "./dist/index.js",
@@ -46,7 +46,8 @@
46
46
  "format": "prettier --write \"src/**/*.{js,ts,tsx}\"",
47
47
  "update-openapi": "tsx ./scripts/update-openapi.cts",
48
48
  "benchmark:build": "tsup src/storage/__benchmarks__/storage.benchmark.ts",
49
- "benchmark:run": "node ./dist/storage.benchmark.js"
49
+ "benchmark:run": "node ./dist/storage.benchmark.js",
50
+ "document": "api-extractor run --local"
50
51
  },
51
52
  "devDependencies": {
52
53
  "@types/js-cookie": "3.0.2",
@@ -65,5 +66,5 @@
65
66
  "publishConfig": {
66
67
  "access": "public"
67
68
  },
68
- "gitHead": "77f2eaabc380a8251c040f8bdd21d5451351022f"
69
+ "gitHead": "bd4414826a6d38b928b5ba2ea68e58160b784562"
69
70
  }