@ninetailed/experience.js 3.0.0-beta.32 → 3.0.0-beta.34

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/index.cjs CHANGED
@@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var unionBy = require('lodash/unionBy');
6
6
  var experience_jsShared = require('@ninetailed/experience.js-shared');
7
7
  var Analytics = require('analytics');
8
+ var experience_jsPluginAnalytics = require('@ninetailed/experience.js-plugin-analytics');
8
9
  var flatten = require('lodash/flatten');
9
10
  var find = require('lodash/find');
10
11
  var includes = require('lodash/includes');
@@ -2586,80 +2587,74 @@ const LEGACY_ANONYMOUS_ID = '__anon_id';
2586
2587
  const ANONYMOUS_ID = '__nt_anonymous_id__';
2587
2588
  const DEBUG_FLAG = '__nt_debug__';
2588
2589
  const PROFILE_FALLBACK_CACHE = '__nt_profile__';
2590
+ const PROFILE_CHANGE = 'profile-change';
2591
+ const PROFILE_RESET = 'profile-reset';
2589
2592
 
2590
- const NINETAILED_TRACKER_EVENTS = {
2591
- /**
2592
- * `profile` - Fires when the profile is returned by the cdp API.
2593
- */
2594
- profile: 'profile',
2595
- /**
2596
- * `reset` - gets fired when the profile gets reset, so other plugins can react.
2597
- */
2598
- reset: 'reset-profile'
2599
- };
2600
2593
  const PLUGIN_NAME = 'ninetailed';
2601
2594
  const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
2602
2595
  const ninetailedPlugin = ({
2603
- clientId,
2604
- environment,
2605
- preview: _preview = false,
2606
- url,
2596
+ apiClient,
2607
2597
  profile,
2608
2598
  locale
2609
2599
  }) => {
2610
- const apiClient = new experience_jsShared.NinetailedApiClient({
2611
- clientId,
2612
- environment,
2613
- url
2614
- });
2600
+ let _instance;
2615
2601
  let queue = [];
2616
- const flush = instance => __awaiter(void 0, void 0, void 0, function* () {
2602
+ const flush = () => __awaiter(void 0, void 0, void 0, function* () {
2617
2603
  const events = Object.assign([], queue);
2618
2604
  experience_jsShared.logger.info('Start flushing events.');
2619
2605
  queue = [];
2620
2606
  if (!events.length) {
2621
- return;
2607
+ return {
2608
+ success: true
2609
+ };
2622
2610
  }
2623
2611
  try {
2624
- const anonymousId = instance.storage.getItem(ANONYMOUS_ID);
2612
+ const anonymousId = _instance.storage.getItem(ANONYMOUS_ID);
2625
2613
  const profile = yield apiClient.upsertProfile({
2626
2614
  profileId: anonymousId,
2627
2615
  events
2628
2616
  }, {
2629
2617
  locale
2630
2618
  });
2631
- instance.storage.setItem(ANONYMOUS_ID, profile.id);
2632
- instance.storage.setItem(PROFILE_FALLBACK_CACHE, profile);
2619
+ _instance.storage.setItem(ANONYMOUS_ID, profile.id);
2620
+ _instance.storage.setItem(PROFILE_FALLBACK_CACHE, profile);
2633
2621
  experience_jsShared.logger.debug('Profile from api: ', profile);
2634
- instance.dispatch({
2635
- type: NINETAILED_TRACKER_EVENTS.profile,
2622
+ _instance.dispatch({
2623
+ type: PROFILE_CHANGE,
2636
2624
  profile
2637
2625
  });
2626
+ yield delay(20);
2627
+ return {
2628
+ success: true
2629
+ };
2638
2630
  } catch (error) {
2639
2631
  experience_jsShared.logger.debug('An error occurred during flushing the events: ', error);
2640
- const fallbackProfile = instance.storage.getItem(PROFILE_FALLBACK_CACHE);
2632
+ const fallbackProfile = _instance.storage.getItem(PROFILE_FALLBACK_CACHE);
2641
2633
  if (fallbackProfile) {
2642
2634
  experience_jsShared.logger.debug('Found a fallback profile - will use this.');
2643
- instance.dispatch({
2644
- type: NINETAILED_TRACKER_EVENTS.profile,
2635
+ _instance.dispatch({
2636
+ type: PROFILE_CHANGE,
2645
2637
  profile: fallbackProfile
2646
2638
  });
2639
+ return {
2640
+ success: false
2641
+ };
2647
2642
  } else {
2648
2643
  experience_jsShared.logger.debug('No fallback profile found - setting profile to null.');
2649
- instance.dispatch({
2650
- type: NINETAILED_TRACKER_EVENTS.profile,
2644
+ _instance.dispatch({
2645
+ type: PROFILE_CHANGE,
2646
+ // TODO is it a good idea to set the profile to null?
2651
2647
  profile: null,
2652
2648
  error
2653
2649
  });
2650
+ return {
2651
+ success: false
2652
+ };
2654
2653
  }
2655
2654
  }
2656
- // This is necessary to make sure that the cache is updated before the next flush is performed
2657
- yield delay(20);
2658
2655
  });
2659
- const throttledFlush = asyncThrottle(flush);
2660
- const enqueueEvent = (event, instance) => __awaiter(void 0, void 0, void 0, function* () {
2656
+ const enqueueEvent = event => __awaiter(void 0, void 0, void 0, function* () {
2661
2657
  queue = unionBy__default["default"]([event], queue, 'messageId');
2662
- throttledFlush(instance);
2663
2658
  });
2664
2659
  const abortNonClientEvents = ({
2665
2660
  abort,
@@ -2676,6 +2671,7 @@ const ninetailedPlugin = ({
2676
2671
  initialize: ({
2677
2672
  instance
2678
2673
  }) => {
2674
+ _instance = instance;
2679
2675
  if (instance.storage.getItem(DEBUG_FLAG)) {
2680
2676
  experience_jsShared.logger.addSink(new experience_jsShared.ConsoleLogSink());
2681
2677
  experience_jsShared.logger.info('Ninetailed Debug Mode is enabled.');
@@ -2692,12 +2688,12 @@ const ninetailedPlugin = ({
2692
2688
  }
2693
2689
  experience_jsShared.logger.debug('Ninetailed Core plugin initialized.');
2694
2690
  },
2691
+ flush: asyncThrottle(flush),
2695
2692
  pageStart: params => {
2696
2693
  return abortNonClientEvents(params);
2697
2694
  },
2698
2695
  page: ({
2699
- payload,
2700
- instance
2696
+ payload
2701
2697
  }) => __awaiter(void 0, void 0, void 0, function* () {
2702
2698
  experience_jsShared.logger.info('Sending Page event.');
2703
2699
  const ctx = buildClientNinetailedRequestContext();
@@ -2706,14 +2702,13 @@ const ninetailedPlugin = ({
2706
2702
  timestamp: payload.meta.ts,
2707
2703
  properties: payload.properties,
2708
2704
  ctx
2709
- }), instance);
2705
+ }));
2710
2706
  }),
2711
2707
  trackStart: params => {
2712
2708
  return abortNonClientEvents(params);
2713
2709
  },
2714
2710
  track: ({
2715
- payload,
2716
- instance
2711
+ payload
2717
2712
  }) => __awaiter(void 0, void 0, void 0, function* () {
2718
2713
  experience_jsShared.logger.info('Sending Track event.');
2719
2714
  const ctx = buildClientNinetailedRequestContext();
@@ -2723,14 +2718,13 @@ const ninetailedPlugin = ({
2723
2718
  event: payload.event,
2724
2719
  properties: payload.properties,
2725
2720
  ctx
2726
- }), instance);
2721
+ }));
2727
2722
  }),
2728
2723
  identifyStart: params => {
2729
2724
  return abortNonClientEvents(params);
2730
2725
  },
2731
2726
  identify: ({
2732
- payload,
2733
- instance
2727
+ payload
2734
2728
  }) => __awaiter(void 0, void 0, void 0, function* () {
2735
2729
  experience_jsShared.logger.info('Sending Identify event.');
2736
2730
  const ctx = buildClientNinetailedRequestContext();
@@ -2745,7 +2739,7 @@ const ninetailedPlugin = ({
2745
2739
  traits: payload.traits,
2746
2740
  userId: payload.userId,
2747
2741
  ctx
2748
- }), instance);
2742
+ }));
2749
2743
  }),
2750
2744
  setItemStart: ({
2751
2745
  abort,
@@ -2762,10 +2756,10 @@ const ninetailedPlugin = ({
2762
2756
  experience_jsShared.logger.debug('Resetting profile.');
2763
2757
  const instance = args[args.length - 1];
2764
2758
  instance.dispatch({
2765
- type: NINETAILED_TRACKER_EVENTS.reset
2759
+ type: PROFILE_RESET
2766
2760
  });
2767
- yield instance.storage.removeItem(ANONYMOUS_ID);
2768
- yield instance.storage.removeItem(PROFILE_FALLBACK_CACHE);
2761
+ instance.storage.removeItem(ANONYMOUS_ID);
2762
+ instance.storage.removeItem(PROFILE_FALLBACK_CACHE);
2769
2763
  experience_jsShared.logger.debug('Removed old profile data from localstorage.');
2770
2764
  // sending a new page event, when no anonymousId is set will create a new profile.
2771
2765
  yield instance.page();
@@ -2777,11 +2771,11 @@ const ninetailedPlugin = ({
2777
2771
  const instance = args[args.length - 1];
2778
2772
  const consoleLogSink = new experience_jsShared.ConsoleLogSink();
2779
2773
  if (enabled) {
2780
- yield instance.storage.setItem(DEBUG_FLAG, true);
2774
+ instance.storage.setItem(DEBUG_FLAG, true);
2781
2775
  experience_jsShared.logger.addSink(consoleLogSink);
2782
2776
  experience_jsShared.logger.info('Debug mode enabled.');
2783
2777
  } else {
2784
- yield instance.storage.removeItem(DEBUG_FLAG);
2778
+ instance.storage.removeItem(DEBUG_FLAG);
2785
2779
  experience_jsShared.logger.info('Debug mode disabled.');
2786
2780
  experience_jsShared.logger.removeSink(consoleLogSink.name);
2787
2781
  }
@@ -3188,11 +3182,7 @@ for (var COLLECTION_NAME in DOMIterables) {
3188
3182
  handlePrototype(DOMTokenListPrototype, 'DOMTokenList');
3189
3183
 
3190
3184
  class Ninetailed {
3191
- constructor({
3192
- clientId,
3193
- environment,
3194
- preview
3195
- }, {
3185
+ constructor(ninetailedApiClientInstanceOrOptions, {
3196
3186
  plugins,
3197
3187
  url,
3198
3188
  profile,
@@ -3203,47 +3193,65 @@ class Ninetailed {
3203
3193
  } = {}) {
3204
3194
  this.isInitialized = false;
3205
3195
  this.page = (data, options) => __awaiter(this, void 0, void 0, function* () {
3206
- const result = experience_jsShared.PageviewProperties.partial().default({}).safeParse(data);
3207
- if (!result.success) {
3208
- throw new Error(`[Validation Error] "page" was called with invalid params. Page data is not valid: ${result.error.format()}`);
3196
+ try {
3197
+ const result = experience_jsShared.PageviewProperties.partial().default({}).safeParse(data);
3198
+ if (!result.success) {
3199
+ throw new Error(`[Validation Error] "page" was called with invalid params. Page data is not valid: ${result.error.format()}`);
3200
+ }
3201
+ yield this.waitUntilInitialized();
3202
+ yield this.instance.page(data, this.buildOptions(options));
3203
+ return this.eventQueue.flush();
3204
+ } catch (error) {
3205
+ experience_jsShared.logger.error(error);
3206
+ if (error instanceof RangeError) {
3207
+ throw new Error(`[Validation Error] "page" was called with invalid params. Could not validate due to "RangeError: Maximum call stack size exceeded". This can be caused by passing a cyclic data structure as a parameter. Refrain from passing a cyclic data structure or sanitize it beforehand.`);
3208
+ }
3209
+ throw error;
3209
3210
  }
3210
- yield this.waitUntilInitialized();
3211
- return this.instance.page(data, this.buildOptions(options));
3212
3211
  });
3213
3212
  this.track = (event, properties, options) => __awaiter(this, void 0, void 0, function* () {
3214
- const result = experience_jsShared.Properties.default({}).safeParse(properties);
3215
- if (!result.success) {
3216
- throw new Error(`[Validation Error] "track" was called with invalid params. Properties are no valid json object: ${result.error.format()}`);
3213
+ try {
3214
+ const result = experience_jsShared.Properties.default({}).safeParse(properties);
3215
+ if (!result.success) {
3216
+ throw new Error(`[Validation Error] "track" was called with invalid params. Properties are no valid json object: ${result.error.format()}`);
3217
+ }
3218
+ yield this.waitUntilInitialized();
3219
+ yield this.instance.track(event.toString(), result.data, this.buildOptions(options));
3220
+ return this.eventQueue.flush();
3221
+ } catch (error) {
3222
+ experience_jsShared.logger.error(error);
3223
+ if (error instanceof RangeError) {
3224
+ throw new Error(`[Validation Error] "track" was called with invalid params. Could not validate due to "RangeError: Maximum call stack size exceeded". This can be caused by passing a cyclic data structure as a parameter. Refrain from passing a cyclic data structure or sanitize it beforehand.`);
3225
+ }
3226
+ throw error;
3217
3227
  }
3218
- yield this.waitUntilInitialized();
3219
- return this.instance.track(event.toString(), properties, this.buildOptions(options));
3220
3228
  });
3221
- this.trackHasSeenComponent = payload => __awaiter(this, void 0, void 0, function* () {
3222
- return this.track('hasSeenComponent', payload, {
3223
- plugins: {
3224
- all: true,
3225
- ninetailed: false
3226
- }
3227
- });
3229
+ this.trackHasSeenComponent = properties => __awaiter(this, void 0, void 0, function* () {
3230
+ return this.instance.dispatch(Object.assign(Object.assign({}, properties), {
3231
+ type: experience_jsPluginAnalytics.HAS_SEEN_COMPONENT
3232
+ }));
3228
3233
  });
3229
- this.trackExperience = properties => {
3230
- // we stringify and parse the properties to remove non serializable values
3231
- const stringifiedProperties = JSON.stringify(properties);
3232
- const sanitizedProperties = JSON.parse(stringifiedProperties);
3233
- return this.track('nt_experience', sanitizedProperties, {
3234
- plugins: {
3235
- all: true,
3236
- ninetailed: false
3237
- }
3238
- });
3234
+ this.trackHasSeenExperience = properties => {
3235
+ return this.instance.dispatch(Object.assign(Object.assign({}, properties), {
3236
+ type: experience_jsPluginAnalytics.HAS_SEEN_EXPERIENCE
3237
+ }));
3239
3238
  };
3240
3239
  this.identify = (uid, traits, options) => __awaiter(this, void 0, void 0, function* () {
3241
- const result = experience_jsShared.Traits.default({}).safeParse(traits);
3242
- if (!result.success) {
3243
- throw new Error(`[Validation Error] "identify" was called with invalid params. Traits are no valid json: ${result.error.format()}`);
3240
+ try {
3241
+ const result = experience_jsShared.Traits.default({}).safeParse(traits);
3242
+ if (!result.success) {
3243
+ throw new Error(`[Validation Error] "identify" was called with invalid params. Traits are no valid json: ${result.error.format()}`);
3244
+ }
3245
+ yield this.waitUntilInitialized();
3246
+ yield this.instance.identify(uid.toString(), result.data, this.buildOptions(options));
3247
+ return this.eventQueue.flush();
3248
+ } catch (error) {
3249
+ experience_jsShared.logger.error(error);
3250
+ if (error instanceof RangeError) {
3251
+ throw new Error(`[Validation Error] "identify" was called with invalid params. Could not validate due to "RangeError: Maximum call stack size exceeded". This can be caused by passing a cyclic data structure as a parameter. Refrain from passing a cyclic data structure or sanitize it beforehand.`);
3252
+ }
3253
+ throw error;
3244
3254
  }
3245
- yield this.waitUntilInitialized();
3246
- return this.instance.identify(uid.toString(), result.data, this.buildOptions(options));
3247
3255
  });
3248
3256
  this.reset = () => {
3249
3257
  this.onIsInitialized(() => {
@@ -3261,7 +3269,7 @@ class Ninetailed {
3261
3269
  };
3262
3270
  this.onProfileChange = cb => {
3263
3271
  cb(this.profileState);
3264
- return this.instance.on(NINETAILED_TRACKER_EVENTS.profile, ({
3272
+ return this.instance.on(PROFILE_CHANGE, ({
3265
3273
  payload
3266
3274
  }) => {
3267
3275
  if (payload.error) {
@@ -3296,6 +3304,21 @@ class Ninetailed {
3296
3304
  this.onIsInitialized(resolve);
3297
3305
  });
3298
3306
  };
3307
+ if (ninetailedApiClientInstanceOrOptions instanceof experience_jsShared.NinetailedApiClient) {
3308
+ this.apiClient = ninetailedApiClientInstanceOrOptions;
3309
+ } else {
3310
+ const {
3311
+ clientId,
3312
+ environment,
3313
+ preview
3314
+ } = ninetailedApiClientInstanceOrOptions;
3315
+ this.apiClient = new experience_jsShared.NinetailedApiClient({
3316
+ clientId,
3317
+ environment,
3318
+ url,
3319
+ preview
3320
+ });
3321
+ }
3299
3322
  this.plugins = flatten__default["default"](plugins || []);
3300
3323
  if (profile) {
3301
3324
  this._profileState = {
@@ -3319,17 +3342,15 @@ class Ninetailed {
3319
3342
  experience_jsShared.logger.addSink(new experience_jsShared.OnErrorLogSink(onError));
3320
3343
  }
3321
3344
  this.logger = experience_jsShared.logger;
3345
+ this.eventQueue = ninetailedPlugin({
3346
+ apiClient: this.apiClient,
3347
+ profile,
3348
+ locale,
3349
+ requestTimeout
3350
+ });
3322
3351
  this.instance = Analytics__default["default"]({
3323
3352
  app: 'ninetailed',
3324
- plugins: [...this.plugins, ninetailedPlugin({
3325
- clientId,
3326
- environment,
3327
- url,
3328
- profile,
3329
- locale,
3330
- requestTimeout,
3331
- preview
3332
- })]
3353
+ plugins: [...this.plugins, this.eventQueue]
3333
3354
  });
3334
3355
  const detachOnReadyListener = this.instance.on('ready', () => {
3335
3356
  this.isInitialized = true;
@@ -3412,8 +3433,6 @@ const selectVariant$1 = (baseline, variants, {
3412
3433
  return includes__default["default"](profile === null || profile === void 0 ? void 0 : profile.audiences, (_a = variant.audience) === null || _a === void 0 ? void 0 : _a.id);
3413
3434
  });
3414
3435
  if (variant) {
3415
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3416
- // @ts-ignore
3417
3436
  if ((options === null || options === void 0 ? void 0 : options.holdout) || -1 > (profile === null || profile === void 0 ? void 0 : profile.random)) {
3418
3437
  return {
3419
3438
  loading: false,
@@ -4303,10 +4322,11 @@ exports.ANONYMOUS_ID = ANONYMOUS_ID;
4303
4322
  exports.DEBUG_FLAG = DEBUG_FLAG;
4304
4323
  exports.EXPERIENCE_TRAIT_PREFIX = EXPERIENCE_TRAIT_PREFIX;
4305
4324
  exports.LEGACY_ANONYMOUS_ID = LEGACY_ANONYMOUS_ID;
4306
- exports.NINETAILED_TRACKER_EVENTS = NINETAILED_TRACKER_EVENTS;
4307
4325
  exports.Ninetailed = Ninetailed;
4308
4326
  exports.PLUGIN_NAME = PLUGIN_NAME;
4327
+ exports.PROFILE_CHANGE = PROFILE_CHANGE;
4309
4328
  exports.PROFILE_FALLBACK_CACHE = PROFILE_FALLBACK_CACHE;
4329
+ exports.PROFILE_RESET = PROFILE_RESET;
4310
4330
  exports.decodeExperienceVariantsMap = decodeExperienceVariantsMap;
4311
4331
  exports.isExperienceMatch = isExperienceMatch;
4312
4332
  exports.ninetailedPlugin = ninetailedPlugin;
package/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import unionBy from 'lodash/unionBy';
2
- import { NinetailedApiClient, logger, ConsoleLogSink, buildPageEvent, buildTrackEvent, buildIdentifyEvent, OnLogLogSink, OnErrorLogSink, PageviewProperties, Properties, Traits } from '@ninetailed/experience.js-shared';
2
+ import { logger, ConsoleLogSink, buildPageEvent, buildTrackEvent, buildIdentifyEvent, NinetailedApiClient, OnLogLogSink, OnErrorLogSink, PageviewProperties, Properties, Traits } from '@ninetailed/experience.js-shared';
3
3
  import Analytics from 'analytics';
4
+ import { HAS_SEEN_EXPERIENCE, HAS_SEEN_COMPONENT } from '@ninetailed/experience.js-plugin-analytics';
4
5
  import flatten from 'lodash/flatten';
5
6
  import find from 'lodash/find';
6
7
  import includes from 'lodash/includes';
@@ -2573,80 +2574,74 @@ const LEGACY_ANONYMOUS_ID = '__anon_id';
2573
2574
  const ANONYMOUS_ID = '__nt_anonymous_id__';
2574
2575
  const DEBUG_FLAG = '__nt_debug__';
2575
2576
  const PROFILE_FALLBACK_CACHE = '__nt_profile__';
2577
+ const PROFILE_CHANGE = 'profile-change';
2578
+ const PROFILE_RESET = 'profile-reset';
2576
2579
 
2577
- const NINETAILED_TRACKER_EVENTS = {
2578
- /**
2579
- * `profile` - Fires when the profile is returned by the cdp API.
2580
- */
2581
- profile: 'profile',
2582
- /**
2583
- * `reset` - gets fired when the profile gets reset, so other plugins can react.
2584
- */
2585
- reset: 'reset-profile'
2586
- };
2587
2580
  const PLUGIN_NAME = 'ninetailed';
2588
2581
  const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
2589
2582
  const ninetailedPlugin = ({
2590
- clientId,
2591
- environment,
2592
- preview: _preview = false,
2593
- url,
2583
+ apiClient,
2594
2584
  profile,
2595
2585
  locale
2596
2586
  }) => {
2597
- const apiClient = new NinetailedApiClient({
2598
- clientId,
2599
- environment,
2600
- url
2601
- });
2587
+ let _instance;
2602
2588
  let queue = [];
2603
- const flush = instance => __awaiter(void 0, void 0, void 0, function* () {
2589
+ const flush = () => __awaiter(void 0, void 0, void 0, function* () {
2604
2590
  const events = Object.assign([], queue);
2605
2591
  logger.info('Start flushing events.');
2606
2592
  queue = [];
2607
2593
  if (!events.length) {
2608
- return;
2594
+ return {
2595
+ success: true
2596
+ };
2609
2597
  }
2610
2598
  try {
2611
- const anonymousId = instance.storage.getItem(ANONYMOUS_ID);
2599
+ const anonymousId = _instance.storage.getItem(ANONYMOUS_ID);
2612
2600
  const profile = yield apiClient.upsertProfile({
2613
2601
  profileId: anonymousId,
2614
2602
  events
2615
2603
  }, {
2616
2604
  locale
2617
2605
  });
2618
- instance.storage.setItem(ANONYMOUS_ID, profile.id);
2619
- instance.storage.setItem(PROFILE_FALLBACK_CACHE, profile);
2606
+ _instance.storage.setItem(ANONYMOUS_ID, profile.id);
2607
+ _instance.storage.setItem(PROFILE_FALLBACK_CACHE, profile);
2620
2608
  logger.debug('Profile from api: ', profile);
2621
- instance.dispatch({
2622
- type: NINETAILED_TRACKER_EVENTS.profile,
2609
+ _instance.dispatch({
2610
+ type: PROFILE_CHANGE,
2623
2611
  profile
2624
2612
  });
2613
+ yield delay(20);
2614
+ return {
2615
+ success: true
2616
+ };
2625
2617
  } catch (error) {
2626
2618
  logger.debug('An error occurred during flushing the events: ', error);
2627
- const fallbackProfile = instance.storage.getItem(PROFILE_FALLBACK_CACHE);
2619
+ const fallbackProfile = _instance.storage.getItem(PROFILE_FALLBACK_CACHE);
2628
2620
  if (fallbackProfile) {
2629
2621
  logger.debug('Found a fallback profile - will use this.');
2630
- instance.dispatch({
2631
- type: NINETAILED_TRACKER_EVENTS.profile,
2622
+ _instance.dispatch({
2623
+ type: PROFILE_CHANGE,
2632
2624
  profile: fallbackProfile
2633
2625
  });
2626
+ return {
2627
+ success: false
2628
+ };
2634
2629
  } else {
2635
2630
  logger.debug('No fallback profile found - setting profile to null.');
2636
- instance.dispatch({
2637
- type: NINETAILED_TRACKER_EVENTS.profile,
2631
+ _instance.dispatch({
2632
+ type: PROFILE_CHANGE,
2633
+ // TODO is it a good idea to set the profile to null?
2638
2634
  profile: null,
2639
2635
  error
2640
2636
  });
2637
+ return {
2638
+ success: false
2639
+ };
2641
2640
  }
2642
2641
  }
2643
- // This is necessary to make sure that the cache is updated before the next flush is performed
2644
- yield delay(20);
2645
2642
  });
2646
- const throttledFlush = asyncThrottle(flush);
2647
- const enqueueEvent = (event, instance) => __awaiter(void 0, void 0, void 0, function* () {
2643
+ const enqueueEvent = event => __awaiter(void 0, void 0, void 0, function* () {
2648
2644
  queue = unionBy([event], queue, 'messageId');
2649
- throttledFlush(instance);
2650
2645
  });
2651
2646
  const abortNonClientEvents = ({
2652
2647
  abort,
@@ -2663,6 +2658,7 @@ const ninetailedPlugin = ({
2663
2658
  initialize: ({
2664
2659
  instance
2665
2660
  }) => {
2661
+ _instance = instance;
2666
2662
  if (instance.storage.getItem(DEBUG_FLAG)) {
2667
2663
  logger.addSink(new ConsoleLogSink());
2668
2664
  logger.info('Ninetailed Debug Mode is enabled.');
@@ -2679,12 +2675,12 @@ const ninetailedPlugin = ({
2679
2675
  }
2680
2676
  logger.debug('Ninetailed Core plugin initialized.');
2681
2677
  },
2678
+ flush: asyncThrottle(flush),
2682
2679
  pageStart: params => {
2683
2680
  return abortNonClientEvents(params);
2684
2681
  },
2685
2682
  page: ({
2686
- payload,
2687
- instance
2683
+ payload
2688
2684
  }) => __awaiter(void 0, void 0, void 0, function* () {
2689
2685
  logger.info('Sending Page event.');
2690
2686
  const ctx = buildClientNinetailedRequestContext();
@@ -2693,14 +2689,13 @@ const ninetailedPlugin = ({
2693
2689
  timestamp: payload.meta.ts,
2694
2690
  properties: payload.properties,
2695
2691
  ctx
2696
- }), instance);
2692
+ }));
2697
2693
  }),
2698
2694
  trackStart: params => {
2699
2695
  return abortNonClientEvents(params);
2700
2696
  },
2701
2697
  track: ({
2702
- payload,
2703
- instance
2698
+ payload
2704
2699
  }) => __awaiter(void 0, void 0, void 0, function* () {
2705
2700
  logger.info('Sending Track event.');
2706
2701
  const ctx = buildClientNinetailedRequestContext();
@@ -2710,14 +2705,13 @@ const ninetailedPlugin = ({
2710
2705
  event: payload.event,
2711
2706
  properties: payload.properties,
2712
2707
  ctx
2713
- }), instance);
2708
+ }));
2714
2709
  }),
2715
2710
  identifyStart: params => {
2716
2711
  return abortNonClientEvents(params);
2717
2712
  },
2718
2713
  identify: ({
2719
- payload,
2720
- instance
2714
+ payload
2721
2715
  }) => __awaiter(void 0, void 0, void 0, function* () {
2722
2716
  logger.info('Sending Identify event.');
2723
2717
  const ctx = buildClientNinetailedRequestContext();
@@ -2732,7 +2726,7 @@ const ninetailedPlugin = ({
2732
2726
  traits: payload.traits,
2733
2727
  userId: payload.userId,
2734
2728
  ctx
2735
- }), instance);
2729
+ }));
2736
2730
  }),
2737
2731
  setItemStart: ({
2738
2732
  abort,
@@ -2749,10 +2743,10 @@ const ninetailedPlugin = ({
2749
2743
  logger.debug('Resetting profile.');
2750
2744
  const instance = args[args.length - 1];
2751
2745
  instance.dispatch({
2752
- type: NINETAILED_TRACKER_EVENTS.reset
2746
+ type: PROFILE_RESET
2753
2747
  });
2754
- yield instance.storage.removeItem(ANONYMOUS_ID);
2755
- yield instance.storage.removeItem(PROFILE_FALLBACK_CACHE);
2748
+ instance.storage.removeItem(ANONYMOUS_ID);
2749
+ instance.storage.removeItem(PROFILE_FALLBACK_CACHE);
2756
2750
  logger.debug('Removed old profile data from localstorage.');
2757
2751
  // sending a new page event, when no anonymousId is set will create a new profile.
2758
2752
  yield instance.page();
@@ -2764,11 +2758,11 @@ const ninetailedPlugin = ({
2764
2758
  const instance = args[args.length - 1];
2765
2759
  const consoleLogSink = new ConsoleLogSink();
2766
2760
  if (enabled) {
2767
- yield instance.storage.setItem(DEBUG_FLAG, true);
2761
+ instance.storage.setItem(DEBUG_FLAG, true);
2768
2762
  logger.addSink(consoleLogSink);
2769
2763
  logger.info('Debug mode enabled.');
2770
2764
  } else {
2771
- yield instance.storage.removeItem(DEBUG_FLAG);
2765
+ instance.storage.removeItem(DEBUG_FLAG);
2772
2766
  logger.info('Debug mode disabled.');
2773
2767
  logger.removeSink(consoleLogSink.name);
2774
2768
  }
@@ -3175,11 +3169,7 @@ for (var COLLECTION_NAME in DOMIterables) {
3175
3169
  handlePrototype(DOMTokenListPrototype, 'DOMTokenList');
3176
3170
 
3177
3171
  class Ninetailed {
3178
- constructor({
3179
- clientId,
3180
- environment,
3181
- preview
3182
- }, {
3172
+ constructor(ninetailedApiClientInstanceOrOptions, {
3183
3173
  plugins,
3184
3174
  url,
3185
3175
  profile,
@@ -3190,47 +3180,65 @@ class Ninetailed {
3190
3180
  } = {}) {
3191
3181
  this.isInitialized = false;
3192
3182
  this.page = (data, options) => __awaiter(this, void 0, void 0, function* () {
3193
- const result = PageviewProperties.partial().default({}).safeParse(data);
3194
- if (!result.success) {
3195
- throw new Error(`[Validation Error] "page" was called with invalid params. Page data is not valid: ${result.error.format()}`);
3183
+ try {
3184
+ const result = PageviewProperties.partial().default({}).safeParse(data);
3185
+ if (!result.success) {
3186
+ throw new Error(`[Validation Error] "page" was called with invalid params. Page data is not valid: ${result.error.format()}`);
3187
+ }
3188
+ yield this.waitUntilInitialized();
3189
+ yield this.instance.page(data, this.buildOptions(options));
3190
+ return this.eventQueue.flush();
3191
+ } catch (error) {
3192
+ logger.error(error);
3193
+ if (error instanceof RangeError) {
3194
+ throw new Error(`[Validation Error] "page" was called with invalid params. Could not validate due to "RangeError: Maximum call stack size exceeded". This can be caused by passing a cyclic data structure as a parameter. Refrain from passing a cyclic data structure or sanitize it beforehand.`);
3195
+ }
3196
+ throw error;
3196
3197
  }
3197
- yield this.waitUntilInitialized();
3198
- return this.instance.page(data, this.buildOptions(options));
3199
3198
  });
3200
3199
  this.track = (event, properties, options) => __awaiter(this, void 0, void 0, function* () {
3201
- const result = Properties.default({}).safeParse(properties);
3202
- if (!result.success) {
3203
- throw new Error(`[Validation Error] "track" was called with invalid params. Properties are no valid json object: ${result.error.format()}`);
3200
+ try {
3201
+ const result = Properties.default({}).safeParse(properties);
3202
+ if (!result.success) {
3203
+ throw new Error(`[Validation Error] "track" was called with invalid params. Properties are no valid json object: ${result.error.format()}`);
3204
+ }
3205
+ yield this.waitUntilInitialized();
3206
+ yield this.instance.track(event.toString(), result.data, this.buildOptions(options));
3207
+ return this.eventQueue.flush();
3208
+ } catch (error) {
3209
+ logger.error(error);
3210
+ if (error instanceof RangeError) {
3211
+ throw new Error(`[Validation Error] "track" was called with invalid params. Could not validate due to "RangeError: Maximum call stack size exceeded". This can be caused by passing a cyclic data structure as a parameter. Refrain from passing a cyclic data structure or sanitize it beforehand.`);
3212
+ }
3213
+ throw error;
3204
3214
  }
3205
- yield this.waitUntilInitialized();
3206
- return this.instance.track(event.toString(), properties, this.buildOptions(options));
3207
3215
  });
3208
- this.trackHasSeenComponent = payload => __awaiter(this, void 0, void 0, function* () {
3209
- return this.track('hasSeenComponent', payload, {
3210
- plugins: {
3211
- all: true,
3212
- ninetailed: false
3213
- }
3214
- });
3216
+ this.trackHasSeenComponent = properties => __awaiter(this, void 0, void 0, function* () {
3217
+ return this.instance.dispatch(Object.assign(Object.assign({}, properties), {
3218
+ type: HAS_SEEN_COMPONENT
3219
+ }));
3215
3220
  });
3216
- this.trackExperience = properties => {
3217
- // we stringify and parse the properties to remove non serializable values
3218
- const stringifiedProperties = JSON.stringify(properties);
3219
- const sanitizedProperties = JSON.parse(stringifiedProperties);
3220
- return this.track('nt_experience', sanitizedProperties, {
3221
- plugins: {
3222
- all: true,
3223
- ninetailed: false
3224
- }
3225
- });
3221
+ this.trackHasSeenExperience = properties => {
3222
+ return this.instance.dispatch(Object.assign(Object.assign({}, properties), {
3223
+ type: HAS_SEEN_EXPERIENCE
3224
+ }));
3226
3225
  };
3227
3226
  this.identify = (uid, traits, options) => __awaiter(this, void 0, void 0, function* () {
3228
- const result = Traits.default({}).safeParse(traits);
3229
- if (!result.success) {
3230
- throw new Error(`[Validation Error] "identify" was called with invalid params. Traits are no valid json: ${result.error.format()}`);
3227
+ try {
3228
+ const result = Traits.default({}).safeParse(traits);
3229
+ if (!result.success) {
3230
+ throw new Error(`[Validation Error] "identify" was called with invalid params. Traits are no valid json: ${result.error.format()}`);
3231
+ }
3232
+ yield this.waitUntilInitialized();
3233
+ yield this.instance.identify(uid.toString(), result.data, this.buildOptions(options));
3234
+ return this.eventQueue.flush();
3235
+ } catch (error) {
3236
+ logger.error(error);
3237
+ if (error instanceof RangeError) {
3238
+ throw new Error(`[Validation Error] "identify" was called with invalid params. Could not validate due to "RangeError: Maximum call stack size exceeded". This can be caused by passing a cyclic data structure as a parameter. Refrain from passing a cyclic data structure or sanitize it beforehand.`);
3239
+ }
3240
+ throw error;
3231
3241
  }
3232
- yield this.waitUntilInitialized();
3233
- return this.instance.identify(uid.toString(), result.data, this.buildOptions(options));
3234
3242
  });
3235
3243
  this.reset = () => {
3236
3244
  this.onIsInitialized(() => {
@@ -3248,7 +3256,7 @@ class Ninetailed {
3248
3256
  };
3249
3257
  this.onProfileChange = cb => {
3250
3258
  cb(this.profileState);
3251
- return this.instance.on(NINETAILED_TRACKER_EVENTS.profile, ({
3259
+ return this.instance.on(PROFILE_CHANGE, ({
3252
3260
  payload
3253
3261
  }) => {
3254
3262
  if (payload.error) {
@@ -3283,6 +3291,21 @@ class Ninetailed {
3283
3291
  this.onIsInitialized(resolve);
3284
3292
  });
3285
3293
  };
3294
+ if (ninetailedApiClientInstanceOrOptions instanceof NinetailedApiClient) {
3295
+ this.apiClient = ninetailedApiClientInstanceOrOptions;
3296
+ } else {
3297
+ const {
3298
+ clientId,
3299
+ environment,
3300
+ preview
3301
+ } = ninetailedApiClientInstanceOrOptions;
3302
+ this.apiClient = new NinetailedApiClient({
3303
+ clientId,
3304
+ environment,
3305
+ url,
3306
+ preview
3307
+ });
3308
+ }
3286
3309
  this.plugins = flatten(plugins || []);
3287
3310
  if (profile) {
3288
3311
  this._profileState = {
@@ -3306,17 +3329,15 @@ class Ninetailed {
3306
3329
  logger.addSink(new OnErrorLogSink(onError));
3307
3330
  }
3308
3331
  this.logger = logger;
3332
+ this.eventQueue = ninetailedPlugin({
3333
+ apiClient: this.apiClient,
3334
+ profile,
3335
+ locale,
3336
+ requestTimeout
3337
+ });
3309
3338
  this.instance = Analytics({
3310
3339
  app: 'ninetailed',
3311
- plugins: [...this.plugins, ninetailedPlugin({
3312
- clientId,
3313
- environment,
3314
- url,
3315
- profile,
3316
- locale,
3317
- requestTimeout,
3318
- preview
3319
- })]
3340
+ plugins: [...this.plugins, this.eventQueue]
3320
3341
  });
3321
3342
  const detachOnReadyListener = this.instance.on('ready', () => {
3322
3343
  this.isInitialized = true;
@@ -3399,8 +3420,6 @@ const selectVariant$1 = (baseline, variants, {
3399
3420
  return includes(profile === null || profile === void 0 ? void 0 : profile.audiences, (_a = variant.audience) === null || _a === void 0 ? void 0 : _a.id);
3400
3421
  });
3401
3422
  if (variant) {
3402
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3403
- // @ts-ignore
3404
3423
  if ((options === null || options === void 0 ? void 0 : options.holdout) || -1 > (profile === null || profile === void 0 ? void 0 : profile.random)) {
3405
3424
  return {
3406
3425
  loading: false,
@@ -4286,4 +4305,4 @@ const decodeExperienceVariantsMap = encodedExperienceVariantsMap => {
4286
4305
  }), {});
4287
4306
  };
4288
4307
 
4289
- export { ANONYMOUS_ID, DEBUG_FLAG, EXPERIENCE_TRAIT_PREFIX, LEGACY_ANONYMOUS_ID, NINETAILED_TRACKER_EVENTS, Ninetailed, PLUGIN_NAME, PROFILE_FALLBACK_CACHE, decodeExperienceVariantsMap, isExperienceMatch, ninetailedPlugin, selectActiveExperiments, selectDistribution, selectEligibleExperiences, selectExperience, selectBaselineWithVariants as selectExperienceBaselineWithVariants, selectVariant as selectExperienceVariant, selectVariants as selectExperienceVariants, selectHasVariants as selectHasExperienceVariants, selectVariant$1 as selectVariant };
4308
+ export { ANONYMOUS_ID, DEBUG_FLAG, EXPERIENCE_TRAIT_PREFIX, LEGACY_ANONYMOUS_ID, Ninetailed, PLUGIN_NAME, PROFILE_CHANGE, PROFILE_FALLBACK_CACHE, PROFILE_RESET, decodeExperienceVariantsMap, isExperienceMatch, ninetailedPlugin, selectActiveExperiments, selectDistribution, selectEligibleExperiences, selectExperience, selectBaselineWithVariants as selectExperienceBaselineWithVariants, selectVariant as selectExperienceVariant, selectVariants as selectExperienceVariants, selectHasVariants as selectHasExperienceVariants, selectVariant$1 as selectVariant };
@@ -1,7 +1,8 @@
1
1
  import { AnalyticsPlugin, DetachListeners } from 'analytics';
2
- import { Locale, Traits, Profile, Variant, OnLogHandler, OnErrorHandler, Logger, PageviewProperties, Properties } from '@ninetailed/experience.js-shared';
2
+ import { Locale, Traits, Profile, OnLogHandler, OnErrorHandler, Logger, PageviewProperties, Properties, NinetailedApiClient, NinetailedApiClientOptions } from '@ninetailed/experience.js-shared';
3
+ import { TrackComponentProperties, TrackExperienceProperties } from '@ninetailed/experience.js-plugin-analytics';
4
+ import { FlushResult } from './analytics';
3
5
  import { ProfileState } from './types';
4
- import { ExperienceConfiguration } from './experience';
5
6
  declare global {
6
7
  interface Window {
7
8
  ninetailed?: {
@@ -29,24 +30,11 @@ declare type EventFunctionOptions = {
29
30
  };
30
31
  };
31
32
  declare type OnProfileChangeCallback = (profile: ProfileState) => void;
32
- export declare type Page = (data?: Partial<PageviewProperties>, options?: EventFunctionOptions) => Promise<void>;
33
- export declare type Track = (event: string, properties?: Properties, options?: EventFunctionOptions) => Promise<void>;
34
- export declare type TrackHasSeenComponent = (payload: {
35
- variant: Variant<unknown>;
36
- audience: {
37
- id: string;
38
- };
39
- isPersonalized: boolean;
40
- }) => Promise<void>;
41
- export declare type TrackExperienceProperties = {
42
- experience: ExperienceConfiguration;
43
- variant: number;
44
- component: {
45
- id: string;
46
- };
47
- };
48
- export declare type TrackExperience = (properties: TrackExperienceProperties) => Promise<void>;
49
- export declare type Identify = (uid: string, traits?: Traits, options?: EventFunctionOptions) => Promise<void>;
33
+ export declare type Page = (data?: Partial<PageviewProperties>, options?: EventFunctionOptions) => Promise<FlushResult>;
34
+ export declare type Track = (event: string, properties?: Properties, options?: EventFunctionOptions) => Promise<FlushResult>;
35
+ export declare type TrackHasSeenComponent = (properties: TrackComponentProperties) => Promise<void>;
36
+ export declare type TrackHasSeenExperience = (properties: TrackExperienceProperties) => Promise<void>;
37
+ export declare type Identify = (uid: string, traits?: Traits, options?: EventFunctionOptions) => Promise<FlushResult>;
50
38
  export declare type Reset = () => void;
51
39
  export declare type Debug = (enable: boolean) => void;
52
40
  export declare type OnProfileChange = (cb: OnProfileChangeCallback) => DetachListeners;
@@ -54,7 +42,7 @@ export interface NinetailedInstance {
54
42
  page: Page;
55
43
  track: Track;
56
44
  trackHasSeenComponent: TrackHasSeenComponent;
57
- trackExperience: TrackExperience;
45
+ trackHasSeenExperience: TrackHasSeenExperience;
58
46
  identify: Identify;
59
47
  reset: Reset;
60
48
  debug: Debug;
@@ -64,22 +52,21 @@ export interface NinetailedInstance {
64
52
  logger: Logger;
65
53
  onIsInitialized: OnIsInitialized;
66
54
  }
55
+ declare type NinetailedApiClientInstanceOrOptions = NinetailedApiClient | NinetailedApiClientOptions;
67
56
  export declare class Ninetailed implements NinetailedInstance {
68
57
  private readonly instance;
69
58
  private _profileState;
70
59
  private isInitialized;
60
+ private readonly apiClient;
61
+ private readonly eventQueue;
71
62
  readonly plugins: AnalyticsPlugin[];
72
63
  readonly logger: Logger;
73
- constructor({ clientId, environment, preview, }: {
74
- clientId: string;
75
- environment?: string;
76
- preview?: boolean;
77
- }, { plugins, url, profile, locale, requestTimeout, onLog, onError, }?: Options);
78
- page: (data?: Partial<PageviewProperties>, options?: EventFunctionOptions) => Promise<any>;
79
- track: (event: string, properties?: Properties, options?: EventFunctionOptions) => Promise<any>;
64
+ constructor(ninetailedApiClientInstanceOrOptions: NinetailedApiClientInstanceOrOptions, { plugins, url, profile, locale, requestTimeout, onLog, onError, }?: Options);
65
+ page: (data?: Partial<PageviewProperties>, options?: EventFunctionOptions) => Promise<FlushResult>;
66
+ track: (event: string, properties?: Properties, options?: EventFunctionOptions) => Promise<FlushResult>;
80
67
  trackHasSeenComponent: TrackHasSeenComponent;
81
- trackExperience: TrackExperience;
82
- identify: (uid: string, traits?: Traits, options?: EventFunctionOptions) => Promise<any>;
68
+ trackHasSeenExperience: TrackHasSeenExperience;
69
+ identify: (uid: string, traits?: Traits, options?: EventFunctionOptions) => Promise<FlushResult>;
83
70
  reset: () => void;
84
71
  debug: (enabled: boolean) => void;
85
72
  onProfileChange: (cb: OnProfileChangeCallback) => DetachListeners;
@@ -2,3 +2,5 @@ export declare const LEGACY_ANONYMOUS_ID = "__anon_id";
2
2
  export declare const ANONYMOUS_ID = "__nt_anonymous_id__";
3
3
  export declare const DEBUG_FLAG = "__nt_debug__";
4
4
  export declare const PROFILE_FALLBACK_CACHE = "__nt_profile__";
5
+ export declare const PROFILE_CHANGE = "profile-change";
6
+ export declare const PROFILE_RESET = "profile-reset";
@@ -1,24 +1,17 @@
1
1
  import { AnalyticsPlugin } from 'analytics';
2
- import { Profile, Locale } from '@ninetailed/experience.js-shared';
2
+ import { Profile, Locale, NinetailedApiClient } from '@ninetailed/experience.js-shared';
3
3
  declare type AnalyticsPluginNinetailedConfig = {
4
- clientId: string;
5
- environment?: string;
6
- preview?: boolean;
7
- url?: string;
4
+ apiClient: NinetailedApiClient;
8
5
  profile?: Profile;
9
6
  locale?: Locale;
10
7
  requestTimeout?: number;
11
8
  };
12
- export declare const NINETAILED_TRACKER_EVENTS: {
13
- /**
14
- * `profile` - Fires when the profile is returned by the cdp API.
15
- */
16
- profile: string;
17
- /**
18
- * `reset` - gets fired when the profile gets reset, so other plugins can react.
19
- */
20
- reset: string;
21
- };
22
9
  export declare const PLUGIN_NAME = "ninetailed";
23
- export declare const ninetailedPlugin: ({ clientId, environment, preview, url, profile, locale, }: AnalyticsPluginNinetailedConfig) => AnalyticsPlugin;
10
+ export declare type FlushResult = {
11
+ success: boolean;
12
+ };
13
+ export interface NinetailedEventQueue extends AnalyticsPlugin {
14
+ flush: () => Promise<FlushResult>;
15
+ }
16
+ export declare const ninetailedPlugin: ({ apiClient, profile, locale, }: AnalyticsPluginNinetailedConfig) => NinetailedEventQueue;
24
17
  export {};
@@ -1,8 +1,8 @@
1
1
  import { Profile } from '@ninetailed/experience.js-shared';
2
2
  import { ExperienceConfiguration } from './types';
3
3
  declare type IsExperienceMatchArgs = {
4
- experience: ExperienceConfiguration;
5
- activeExperiments: ExperienceConfiguration[];
4
+ experience: ExperienceConfiguration<any>;
5
+ activeExperiments: ExperienceConfiguration<any>[];
6
6
  profile: Profile;
7
7
  };
8
8
  export declare const isExperienceMatch: ({ experience, activeExperiments, profile, }: IsExperienceMatchArgs) => boolean;
@@ -1,3 +1,3 @@
1
1
  import { Profile } from '@ninetailed/experience.js-shared';
2
- import { ExperienceConfiguration } from './types';
3
- export declare const selectActiveExperiments: (experiments: ExperienceConfiguration[], profile: Profile) => ExperienceConfiguration[];
2
+ import { ExperienceConfiguration, Reference } from './types';
3
+ export declare const selectActiveExperiments: <Variant extends Reference>(experiments: ExperienceConfiguration<Variant>[], profile: Profile) => ExperienceConfiguration<Variant>[];
@@ -1,2 +1,2 @@
1
- import { Baseline, BaselineWithVariants, ExperienceConfiguration } from './types';
2
- export declare const selectBaselineWithVariants: (experience: ExperienceConfiguration, baseline: Baseline) => BaselineWithVariants | null;
1
+ import { Baseline, BaselineWithVariants, ExperienceConfiguration, Reference } from './types';
2
+ export declare const selectBaselineWithVariants: <Variant extends Reference>(experience: ExperienceConfiguration<Variant>, baseline: Baseline) => BaselineWithVariants<Variant> | null;
@@ -1,8 +1,8 @@
1
1
  import { Profile } from '@ninetailed/experience.js-shared';
2
- import { Distribution, ExperienceConfiguration } from './types';
3
- declare type SelectDistributionArgs = {
4
- experience: ExperienceConfiguration;
2
+ import { Distribution, ExperienceConfiguration, Reference } from './types';
3
+ declare type SelectDistributionArgs<Variant extends Reference> = {
4
+ experience: ExperienceConfiguration<Variant>;
5
5
  profile: Profile;
6
6
  };
7
- export declare const selectDistribution: ({ experience, profile, }: SelectDistributionArgs) => Distribution;
7
+ export declare const selectDistribution: <Variant extends Reference>({ experience, profile, }: SelectDistributionArgs<Variant>) => Distribution;
8
8
  export {};
@@ -1,12 +1,12 @@
1
- import { ExperienceConfiguration } from './types';
2
- declare type SelectEligibleExperiencesArgs = {
3
- experiences: ExperienceConfiguration[];
4
- activeExperiments: ExperienceConfiguration[];
1
+ import { ExperienceConfiguration, Reference } from './types';
2
+ declare type SelectEligibleExperiencesArgs<Variant extends Reference> = {
3
+ experiences: ExperienceConfiguration<Variant>[];
4
+ activeExperiments: ExperienceConfiguration<Variant>[];
5
5
  };
6
6
  /**
7
7
  * We can use any personalization as eligible experience
8
8
  * When going for an experiment we can only select a active experiment when 1 or more experiments are active
9
9
  * If the profile is not in any active experiments, we can select any expermiment
10
10
  */
11
- export declare const selectEligibleExperiences: ({ experiences, activeExperiments, }: SelectEligibleExperiencesArgs) => ExperienceConfiguration[];
11
+ export declare const selectEligibleExperiences: <Variant extends Reference>({ experiences, activeExperiments, }: SelectEligibleExperiencesArgs<Variant>) => ExperienceConfiguration<Variant>[];
12
12
  export {};
@@ -1,9 +1,9 @@
1
1
  import { Profile } from '@ninetailed/experience.js-shared';
2
- import { ExperienceConfiguration } from './types';
3
- declare type SelectExprienceArgs = {
4
- experiences: ExperienceConfiguration[];
5
- activeExperiments: ExperienceConfiguration[];
2
+ import { ExperienceConfiguration, Reference } from './types';
3
+ declare type SelectExprienceArgs<Variant extends Reference> = {
4
+ experiences: ExperienceConfiguration<Variant>[];
5
+ activeExperiments: ExperienceConfiguration<Variant>[];
6
6
  profile: Profile;
7
7
  };
8
- export declare const selectExperience: ({ experiences, activeExperiments, profile, }: SelectExprienceArgs) => ExperienceConfiguration | null;
8
+ export declare const selectExperience: <Variant extends Reference>({ experiences, activeExperiments, profile, }: SelectExprienceArgs<Variant>) => ExperienceConfiguration<Variant> | null;
9
9
  export {};
@@ -1,2 +1,2 @@
1
- import { Baseline, ExperienceConfiguration } from './types';
2
- export declare const selectHasVariants: (experience: ExperienceConfiguration, baseline: Baseline) => boolean;
1
+ import { Baseline, ExperienceConfiguration, Reference } from './types';
2
+ export declare const selectHasVariants: <Variant extends Reference>(experience: ExperienceConfiguration<Variant>, baseline: Baseline) => boolean;
@@ -1,9 +1,9 @@
1
1
  import { Profile } from '@ninetailed/experience.js-shared';
2
- import { Baseline, ExperienceConfiguration, Variant } from './types';
3
- declare type SelectVariantArgs = {
2
+ import { Baseline, ExperienceConfiguration, Reference, VariantRef } from './types';
3
+ declare type SelectVariantArgs<Variant extends Reference> = {
4
4
  baseline: Baseline;
5
- experience: ExperienceConfiguration;
5
+ experience: ExperienceConfiguration<Variant>;
6
6
  profile: Profile;
7
7
  };
8
- export declare const selectVariant: ({ baseline, experience, profile, }: SelectVariantArgs) => Variant | null;
8
+ export declare const selectVariant: <Variant extends Reference>({ baseline, experience, profile, }: SelectVariantArgs<Variant>) => Variant | VariantRef | null;
9
9
  export {};
@@ -1,2 +1,2 @@
1
- import { Baseline, Variant, ExperienceConfiguration } from './types';
2
- export declare const selectVariants: (experience: ExperienceConfiguration, baseline: Baseline) => Variant[];
1
+ import { Baseline, ExperienceConfiguration, Reference, VariantRef } from './types';
2
+ export declare const selectVariants: <Variant extends Reference>(experience: ExperienceConfiguration<Variant>, baseline: Baseline) => (Variant | VariantRef)[];
@@ -1,3 +1,2 @@
1
- export declare type Baseline<P = Record<string, unknown>> = P & {
2
- id: string;
3
- };
1
+ import { Reference } from './Reference';
2
+ export declare type Baseline<P = unknown> = P & Reference;
@@ -1,6 +1,7 @@
1
1
  import { Baseline } from './Baseline';
2
- import { Variant } from './Variant';
3
- export declare type BaselineWithVariants = {
2
+ import { Reference } from './Reference';
3
+ import { VariantRef } from './VariantRef';
4
+ export declare type BaselineWithVariants<Variant extends Reference> = {
4
5
  baseline: Baseline;
5
- variants: Variant<Record<string, unknown>>[];
6
+ variants: (Variant | VariantRef)[];
6
7
  };
@@ -1,7 +1,8 @@
1
1
  import { BaselineWithVariants } from './BaselineWithVariants';
2
2
  import { Distribution } from './Distribution';
3
+ import { Reference } from './Reference';
3
4
  export declare type ExperienceType = 'nt_personalization' | 'nt_experiment';
4
- export declare type ExperienceConfiguration = {
5
+ export declare type ExperienceConfiguration<Variant extends Reference> = {
5
6
  id: string;
6
7
  type: ExperienceType;
7
8
  audience?: {
@@ -9,5 +10,5 @@ export declare type ExperienceConfiguration = {
9
10
  };
10
11
  trafficAllocation: number;
11
12
  distribution: Distribution[];
12
- components: BaselineWithVariants[];
13
+ components: BaselineWithVariants<Variant>[];
13
14
  };
@@ -0,0 +1,3 @@
1
+ export declare type Reference = {
2
+ id: string;
3
+ };
@@ -0,0 +1,4 @@
1
+ export declare type VariantRef = {
2
+ id: string;
3
+ hidden: boolean;
4
+ };
@@ -1,5 +1,6 @@
1
+ export type { Reference } from './Reference';
1
2
  export type { Baseline } from './Baseline';
2
- export type { Variant } from './Variant';
3
+ export type { VariantRef } from './VariantRef';
3
4
  export type { BaselineWithVariants } from './BaselineWithVariants';
4
5
  export type { Distribution } from './Distribution';
5
6
  export type { ExperienceConfiguration, ExperienceType, } from './ExperienceConfiguration';
@@ -1,4 +1,4 @@
1
1
  import { Profile } from '@ninetailed/experience.js-shared';
2
2
  import { ExperienceConfiguration } from './types';
3
- export declare const getTrafficRandom: (profile: Profile, experience: ExperienceConfiguration) => number;
4
- export declare const getDistributionRandom: (profile: Profile, experience: ExperienceConfiguration) => number;
3
+ export declare const getTrafficRandom: (profile: Profile, experience: ExperienceConfiguration<any>) => number;
4
+ export declare const getDistributionRandom: (profile: Profile, experience: ExperienceConfiguration<any>) => number;
package/package.json CHANGED
@@ -1,15 +1,16 @@
1
1
  {
2
2
  "name": "@ninetailed/experience.js",
3
- "version": "3.0.0-beta.32",
3
+ "version": "3.0.0-beta.34",
4
4
  "module": "./index.js",
5
5
  "main": "./index.cjs",
6
6
  "type": "module",
7
7
  "types": "./index.d.ts",
8
8
  "dependencies": {
9
- "@ninetailed/experience.js-shared": "3.0.0-beta.32",
9
+ "@ninetailed/experience.js-shared": "3.0.0-beta.34",
10
10
  "analytics": "0.8.1",
11
11
  "lodash": "4.17.21",
12
- "murmurhash-js": "1.0.0"
12
+ "murmurhash-js": "1.0.0",
13
+ "@ninetailed/experience.js-plugin-analytics": "0.0.1"
13
14
  },
14
15
  "peerDependencies": {}
15
16
  }
@@ -1,4 +0,0 @@
1
- export declare type Variant<P = unknown> = P & {
2
- id: string;
3
- hidden: boolean;
4
- };