@ninetailed/experience.js 7.12.0 → 7.13.0-beta.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/index.cjs.js +171 -4
- package/index.esm.js +181 -5
- package/package.json +3 -3
- package/src/index.d.ts +1 -0
- package/src/lib/Ninetailed.d.ts +3 -1
- package/src/lib/experience/index.d.ts +1 -0
- package/src/lib/experience/makeChangesModificationMiddleware.d.ts +31 -0
- package/src/lib/experience/types/index.d.ts +1 -1
- package/src/lib/guards/hasChangesModificationMiddleware.d.ts +8 -0
- package/src/lib/plugins/selectPluginsHavingChangesModificationMiddleware.d.ts +9 -0
- package/src/lib/types/ProfileChangedPayload.d.ts +2 -1
- package/src/lib/types/interfaces/HasChangesModificationMiddleware.d.ts +30 -0
package/index.cjs.js
CHANGED
|
@@ -559,7 +559,7 @@ const selectPluginsHavingExperienceSelectionMiddleware = plugins => {
|
|
|
559
559
|
return filteredPlugins;
|
|
560
560
|
};
|
|
561
561
|
|
|
562
|
-
const createPassThroughMiddleware = () => {
|
|
562
|
+
const createPassThroughMiddleware$1 = () => {
|
|
563
563
|
return ({
|
|
564
564
|
experience,
|
|
565
565
|
variant,
|
|
@@ -579,7 +579,7 @@ function createExperienceSelectionMiddleware({
|
|
|
579
579
|
profile
|
|
580
580
|
}) {
|
|
581
581
|
if (profile === null) {
|
|
582
|
-
return createPassThroughMiddleware();
|
|
582
|
+
return createPassThroughMiddleware$1();
|
|
583
583
|
}
|
|
584
584
|
const pluginsWithMiddleware = selectPluginsHavingExperienceSelectionMiddleware(plugins);
|
|
585
585
|
const middlewareFunctions = [];
|
|
@@ -631,6 +631,110 @@ const makeExperienceSelectMiddleware = ({
|
|
|
631
631
|
};
|
|
632
632
|
};
|
|
633
633
|
|
|
634
|
+
/**
|
|
635
|
+
* Type guard that checks if an object implements the HasChangesModificationMiddleware interface
|
|
636
|
+
*
|
|
637
|
+
* @param arg Object to check
|
|
638
|
+
* @returns Boolean indicating if the object implements HasChangesModificationMiddleware
|
|
639
|
+
*/
|
|
640
|
+
const hasChangesModificationMiddleware = arg => {
|
|
641
|
+
return typeof arg === 'object' && arg !== null && 'getChangesModificationMiddleware' in arg && typeof arg.getChangesModificationMiddleware === 'function';
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Selects plugins that implement the HasChangesModificationMiddleware interface
|
|
646
|
+
*
|
|
647
|
+
* @param plugins Array of Ninetailed plugins
|
|
648
|
+
* @returns Array of plugins that implement HasChangesModificationMiddleware
|
|
649
|
+
*/
|
|
650
|
+
const selectPluginsHavingChangesModificationMiddleware = plugins => {
|
|
651
|
+
const filteredPlugins = [];
|
|
652
|
+
for (const plugin of plugins) {
|
|
653
|
+
if (hasChangesModificationMiddleware(plugin)) {
|
|
654
|
+
filteredPlugins.push(plugin);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
return filteredPlugins;
|
|
658
|
+
};
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Creates a pass-through middleware that doesn't modify changes
|
|
662
|
+
*/
|
|
663
|
+
const createPassThroughMiddleware = () => {
|
|
664
|
+
return ({
|
|
665
|
+
changes
|
|
666
|
+
}) => {
|
|
667
|
+
return {
|
|
668
|
+
changes
|
|
669
|
+
};
|
|
670
|
+
};
|
|
671
|
+
};
|
|
672
|
+
/**
|
|
673
|
+
* Creates a middleware function by composing middleware from multiple plugins
|
|
674
|
+
*/
|
|
675
|
+
function createChangesModificationMiddleware({
|
|
676
|
+
plugins,
|
|
677
|
+
changes
|
|
678
|
+
}) {
|
|
679
|
+
const pluginsWithMiddleware = selectPluginsHavingChangesModificationMiddleware(plugins);
|
|
680
|
+
const middlewareFunctions = [];
|
|
681
|
+
for (const plugin of pluginsWithMiddleware) {
|
|
682
|
+
const middleware = plugin.getChangesModificationMiddleware({
|
|
683
|
+
changes
|
|
684
|
+
});
|
|
685
|
+
if (middleware !== undefined) {
|
|
686
|
+
middlewareFunctions.push(middleware);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
// If no middleware functions were found, return a pass-through middleware
|
|
690
|
+
if (middlewareFunctions.length === 0) {
|
|
691
|
+
return createPassThroughMiddleware();
|
|
692
|
+
}
|
|
693
|
+
// Compose middleware functions using pipe
|
|
694
|
+
return experience_jsShared.pipe(...middlewareFunctions);
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* Creates a changes modification middleware system with change notification
|
|
698
|
+
*
|
|
699
|
+
* This follows the same pattern as the experience selection middleware system
|
|
700
|
+
*/
|
|
701
|
+
const makeChangesModificationMiddleware = ({
|
|
702
|
+
plugins,
|
|
703
|
+
onChange,
|
|
704
|
+
changes
|
|
705
|
+
}) => {
|
|
706
|
+
let removeChangeListeners = [];
|
|
707
|
+
const pluginsHavingChangeEmitters = selectPluginsHavingOnChangeEmitter(plugins);
|
|
708
|
+
const middleware = createChangesModificationMiddleware({
|
|
709
|
+
plugins,
|
|
710
|
+
changes
|
|
711
|
+
});
|
|
712
|
+
const addListeners = () => {
|
|
713
|
+
removeChangeListeners = pluginsHavingChangeEmitters.map(plugin => {
|
|
714
|
+
const listener = () => {
|
|
715
|
+
// When a plugin changes, recreate the middleware and notify
|
|
716
|
+
const updatedMiddleware = createChangesModificationMiddleware({
|
|
717
|
+
plugins,
|
|
718
|
+
changes
|
|
719
|
+
});
|
|
720
|
+
onChange(updatedMiddleware);
|
|
721
|
+
};
|
|
722
|
+
return plugin.onChangeEmitter.addListener(listener);
|
|
723
|
+
});
|
|
724
|
+
};
|
|
725
|
+
// WARNING: This specific implementation using forEach is required.
|
|
726
|
+
// DO NOT replace with for...of or other loop constructs as they will break functionality.
|
|
727
|
+
// The exact reason is uncertain but appears related to the transpiler.
|
|
728
|
+
const removeListeners = () => {
|
|
729
|
+
removeChangeListeners.forEach(removeListener => removeListener());
|
|
730
|
+
};
|
|
731
|
+
return {
|
|
732
|
+
addListeners,
|
|
733
|
+
removeListeners,
|
|
734
|
+
middleware
|
|
735
|
+
};
|
|
736
|
+
};
|
|
737
|
+
|
|
634
738
|
class EventBuilder {
|
|
635
739
|
constructor(buildRequestContext) {
|
|
636
740
|
this.buildRequestContext = buildRequestContext || buildClientNinetailedRequestContext;
|
|
@@ -1040,15 +1144,77 @@ class Ninetailed {
|
|
|
1040
1144
|
};
|
|
1041
1145
|
/**
|
|
1042
1146
|
* Registers a callback to be notified when changes occur in the profile state.
|
|
1147
|
+
* Uses the changes modification middleware system to process changes.
|
|
1148
|
+
* Changes are processed in the following order:
|
|
1043
1149
|
*
|
|
1044
1150
|
* @param cb - Callback function that receives the changes state
|
|
1045
1151
|
* @returns Function to unsubscribe from changes updates
|
|
1046
1152
|
*/
|
|
1047
1153
|
this.onChangesChange = cb => {
|
|
1154
|
+
// Initially notify with current state
|
|
1048
1155
|
this.notifyChangesCallback(cb, this._profileState);
|
|
1049
|
-
|
|
1050
|
-
|
|
1156
|
+
let middlewareChangeListeners = [];
|
|
1157
|
+
const removeProfileChangeListener = this.onProfileChange(profileState => {
|
|
1158
|
+
// Clean up any existing middleware listeners
|
|
1159
|
+
middlewareChangeListeners.forEach(removeListener => removeListener());
|
|
1160
|
+
middlewareChangeListeners = [];
|
|
1161
|
+
// If we're in loading or error state, simply pass through
|
|
1162
|
+
if (profileState.status !== 'success') {
|
|
1163
|
+
this.notifyChangesCallback(cb, profileState);
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
// Set up middleware for changes
|
|
1167
|
+
const {
|
|
1168
|
+
addListeners,
|
|
1169
|
+
removeListeners,
|
|
1170
|
+
middleware: changesModificationMiddleware
|
|
1171
|
+
} = makeChangesModificationMiddleware({
|
|
1172
|
+
plugins: this.plugins,
|
|
1173
|
+
changes: profileState.changes || [],
|
|
1174
|
+
onChange: updatedMiddleware => {
|
|
1175
|
+
// When plugin state changes, reapply middleware to current changes
|
|
1176
|
+
if (profileState.status === 'success' && profileState.changes) {
|
|
1177
|
+
const {
|
|
1178
|
+
changes: modifiedChanges
|
|
1179
|
+
} = updatedMiddleware({
|
|
1180
|
+
changes: profileState.changes
|
|
1181
|
+
});
|
|
1182
|
+
cb({
|
|
1183
|
+
status: 'success',
|
|
1184
|
+
changes: modifiedChanges,
|
|
1185
|
+
error: null
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
});
|
|
1190
|
+
// Add listeners for plugin changes
|
|
1191
|
+
addListeners();
|
|
1192
|
+
middlewareChangeListeners.push(removeListeners);
|
|
1193
|
+
// Apply middleware to current changes
|
|
1194
|
+
if (profileState.changes) {
|
|
1195
|
+
const {
|
|
1196
|
+
changes: modifiedChanges
|
|
1197
|
+
} = changesModificationMiddleware({
|
|
1198
|
+
changes: profileState.changes
|
|
1199
|
+
});
|
|
1200
|
+
cb({
|
|
1201
|
+
status: 'success',
|
|
1202
|
+
changes: modifiedChanges,
|
|
1203
|
+
error: null
|
|
1204
|
+
});
|
|
1205
|
+
} else {
|
|
1206
|
+
cb({
|
|
1207
|
+
status: 'success',
|
|
1208
|
+
changes: [],
|
|
1209
|
+
error: null
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1051
1212
|
});
|
|
1213
|
+
// Return a function that cleans up all listeners
|
|
1214
|
+
return () => {
|
|
1215
|
+
removeProfileChangeListener();
|
|
1216
|
+
middlewareChangeListeners.forEach(removeListener => removeListener());
|
|
1217
|
+
};
|
|
1052
1218
|
};
|
|
1053
1219
|
this.onIsInitialized = onIsInitializedCallback => {
|
|
1054
1220
|
if (typeof onIsInitializedCallback === 'function') {
|
|
@@ -1411,6 +1577,7 @@ exports.PROFILE_RESET = PROFILE_RESET;
|
|
|
1411
1577
|
exports.SET_ENABLED_FEATURES = SET_ENABLED_FEATURES;
|
|
1412
1578
|
exports.buildClientNinetailedRequestContext = buildClientNinetailedRequestContext;
|
|
1413
1579
|
exports.decodeExperienceVariantsMap = decodeExperienceVariantsMap;
|
|
1580
|
+
exports.makeChangesModificationMiddleware = makeChangesModificationMiddleware;
|
|
1414
1581
|
exports.makeExperienceSelectMiddleware = makeExperienceSelectMiddleware;
|
|
1415
1582
|
exports.selectPluginsHavingExperienceSelectionMiddleware = selectPluginsHavingExperienceSelectionMiddleware;
|
|
1416
1583
|
exports.selectPluginsHavingOnChangeEmitter = selectPluginsHavingOnChangeEmitter;
|
package/index.esm.js
CHANGED
|
@@ -523,7 +523,7 @@ const selectPluginsHavingExperienceSelectionMiddleware = plugins => {
|
|
|
523
523
|
return filteredPlugins;
|
|
524
524
|
};
|
|
525
525
|
|
|
526
|
-
const createPassThroughMiddleware = () => {
|
|
526
|
+
const createPassThroughMiddleware$1 = () => {
|
|
527
527
|
return ({
|
|
528
528
|
experience,
|
|
529
529
|
variant,
|
|
@@ -543,7 +543,7 @@ function createExperienceSelectionMiddleware({
|
|
|
543
543
|
profile
|
|
544
544
|
}) {
|
|
545
545
|
if (profile === null) {
|
|
546
|
-
return createPassThroughMiddleware();
|
|
546
|
+
return createPassThroughMiddleware$1();
|
|
547
547
|
}
|
|
548
548
|
const pluginsWithMiddleware = selectPluginsHavingExperienceSelectionMiddleware(plugins);
|
|
549
549
|
const middlewareFunctions = [];
|
|
@@ -596,6 +596,115 @@ const makeExperienceSelectMiddleware = ({
|
|
|
596
596
|
};
|
|
597
597
|
};
|
|
598
598
|
|
|
599
|
+
/**
|
|
600
|
+
* Type guard that checks if an object implements the HasChangesModificationMiddleware interface
|
|
601
|
+
*
|
|
602
|
+
* @param arg Object to check
|
|
603
|
+
* @returns Boolean indicating if the object implements HasChangesModificationMiddleware
|
|
604
|
+
*/
|
|
605
|
+
const hasChangesModificationMiddleware = arg => {
|
|
606
|
+
return typeof arg === 'object' && arg !== null && 'getChangesModificationMiddleware' in arg && typeof arg.getChangesModificationMiddleware === 'function';
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Selects plugins that implement the HasChangesModificationMiddleware interface
|
|
611
|
+
*
|
|
612
|
+
* @param plugins Array of Ninetailed plugins
|
|
613
|
+
* @returns Array of plugins that implement HasChangesModificationMiddleware
|
|
614
|
+
*/
|
|
615
|
+
const selectPluginsHavingChangesModificationMiddleware = plugins => {
|
|
616
|
+
const filteredPlugins = [];
|
|
617
|
+
for (const plugin of plugins) {
|
|
618
|
+
if (hasChangesModificationMiddleware(plugin)) {
|
|
619
|
+
filteredPlugins.push(plugin);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
return filteredPlugins;
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
/**
|
|
626
|
+
* Creates a pass-through middleware that doesn't modify changes
|
|
627
|
+
*/
|
|
628
|
+
const createPassThroughMiddleware = () => {
|
|
629
|
+
return ({
|
|
630
|
+
changes
|
|
631
|
+
}) => {
|
|
632
|
+
return {
|
|
633
|
+
changes
|
|
634
|
+
};
|
|
635
|
+
};
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* Creates a middleware function by composing middleware from multiple plugins
|
|
640
|
+
*/
|
|
641
|
+
function createChangesModificationMiddleware({
|
|
642
|
+
plugins,
|
|
643
|
+
changes
|
|
644
|
+
}) {
|
|
645
|
+
const pluginsWithMiddleware = selectPluginsHavingChangesModificationMiddleware(plugins);
|
|
646
|
+
const middlewareFunctions = [];
|
|
647
|
+
for (const plugin of pluginsWithMiddleware) {
|
|
648
|
+
const middleware = plugin.getChangesModificationMiddleware({
|
|
649
|
+
changes
|
|
650
|
+
});
|
|
651
|
+
if (middleware !== undefined) {
|
|
652
|
+
middlewareFunctions.push(middleware);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// If no middleware functions were found, return a pass-through middleware
|
|
657
|
+
if (middlewareFunctions.length === 0) {
|
|
658
|
+
return createPassThroughMiddleware();
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// Compose middleware functions using pipe
|
|
662
|
+
return pipe(...middlewareFunctions);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* Creates a changes modification middleware system with change notification
|
|
667
|
+
*
|
|
668
|
+
* This follows the same pattern as the experience selection middleware system
|
|
669
|
+
*/
|
|
670
|
+
const makeChangesModificationMiddleware = ({
|
|
671
|
+
plugins,
|
|
672
|
+
onChange,
|
|
673
|
+
changes
|
|
674
|
+
}) => {
|
|
675
|
+
let removeChangeListeners = [];
|
|
676
|
+
const pluginsHavingChangeEmitters = selectPluginsHavingOnChangeEmitter(plugins);
|
|
677
|
+
const middleware = createChangesModificationMiddleware({
|
|
678
|
+
plugins,
|
|
679
|
+
changes
|
|
680
|
+
});
|
|
681
|
+
const addListeners = () => {
|
|
682
|
+
removeChangeListeners = pluginsHavingChangeEmitters.map(plugin => {
|
|
683
|
+
const listener = () => {
|
|
684
|
+
// When a plugin changes, recreate the middleware and notify
|
|
685
|
+
const updatedMiddleware = createChangesModificationMiddleware({
|
|
686
|
+
plugins,
|
|
687
|
+
changes
|
|
688
|
+
});
|
|
689
|
+
onChange(updatedMiddleware);
|
|
690
|
+
};
|
|
691
|
+
return plugin.onChangeEmitter.addListener(listener);
|
|
692
|
+
});
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
// WARNING: This specific implementation using forEach is required.
|
|
696
|
+
// DO NOT replace with for...of or other loop constructs as they will break functionality.
|
|
697
|
+
// The exact reason is uncertain but appears related to the transpiler.
|
|
698
|
+
const removeListeners = () => {
|
|
699
|
+
removeChangeListeners.forEach(removeListener => removeListener());
|
|
700
|
+
};
|
|
701
|
+
return {
|
|
702
|
+
addListeners,
|
|
703
|
+
removeListeners,
|
|
704
|
+
middleware
|
|
705
|
+
};
|
|
706
|
+
};
|
|
707
|
+
|
|
599
708
|
class EventBuilder {
|
|
600
709
|
constructor(buildRequestContext) {
|
|
601
710
|
this.buildRequestContext = void 0;
|
|
@@ -1023,15 +1132,82 @@ class Ninetailed {
|
|
|
1023
1132
|
};
|
|
1024
1133
|
/**
|
|
1025
1134
|
* Registers a callback to be notified when changes occur in the profile state.
|
|
1135
|
+
* Uses the changes modification middleware system to process changes.
|
|
1136
|
+
* Changes are processed in the following order:
|
|
1026
1137
|
*
|
|
1027
1138
|
* @param cb - Callback function that receives the changes state
|
|
1028
1139
|
* @returns Function to unsubscribe from changes updates
|
|
1029
1140
|
*/
|
|
1030
1141
|
this.onChangesChange = cb => {
|
|
1142
|
+
// Initially notify with current state
|
|
1031
1143
|
this.notifyChangesCallback(cb, this._profileState);
|
|
1032
|
-
|
|
1033
|
-
|
|
1144
|
+
let middlewareChangeListeners = [];
|
|
1145
|
+
const removeProfileChangeListener = this.onProfileChange(profileState => {
|
|
1146
|
+
// Clean up any existing middleware listeners
|
|
1147
|
+
middlewareChangeListeners.forEach(removeListener => removeListener());
|
|
1148
|
+
middlewareChangeListeners = [];
|
|
1149
|
+
|
|
1150
|
+
// If we're in loading or error state, simply pass through
|
|
1151
|
+
if (profileState.status !== 'success') {
|
|
1152
|
+
this.notifyChangesCallback(cb, profileState);
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
// Set up middleware for changes
|
|
1157
|
+
const {
|
|
1158
|
+
addListeners,
|
|
1159
|
+
removeListeners,
|
|
1160
|
+
middleware: changesModificationMiddleware
|
|
1161
|
+
} = makeChangesModificationMiddleware({
|
|
1162
|
+
plugins: this.plugins,
|
|
1163
|
+
changes: profileState.changes || [],
|
|
1164
|
+
onChange: updatedMiddleware => {
|
|
1165
|
+
// When plugin state changes, reapply middleware to current changes
|
|
1166
|
+
if (profileState.status === 'success' && profileState.changes) {
|
|
1167
|
+
const {
|
|
1168
|
+
changes: modifiedChanges
|
|
1169
|
+
} = updatedMiddleware({
|
|
1170
|
+
changes: profileState.changes
|
|
1171
|
+
});
|
|
1172
|
+
cb({
|
|
1173
|
+
status: 'success',
|
|
1174
|
+
changes: modifiedChanges,
|
|
1175
|
+
error: null
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
});
|
|
1180
|
+
|
|
1181
|
+
// Add listeners for plugin changes
|
|
1182
|
+
addListeners();
|
|
1183
|
+
middlewareChangeListeners.push(removeListeners);
|
|
1184
|
+
|
|
1185
|
+
// Apply middleware to current changes
|
|
1186
|
+
if (profileState.changes) {
|
|
1187
|
+
const {
|
|
1188
|
+
changes: modifiedChanges
|
|
1189
|
+
} = changesModificationMiddleware({
|
|
1190
|
+
changes: profileState.changes
|
|
1191
|
+
});
|
|
1192
|
+
cb({
|
|
1193
|
+
status: 'success',
|
|
1194
|
+
changes: modifiedChanges,
|
|
1195
|
+
error: null
|
|
1196
|
+
});
|
|
1197
|
+
} else {
|
|
1198
|
+
cb({
|
|
1199
|
+
status: 'success',
|
|
1200
|
+
changes: [],
|
|
1201
|
+
error: null
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1034
1204
|
});
|
|
1205
|
+
|
|
1206
|
+
// Return a function that cleans up all listeners
|
|
1207
|
+
return () => {
|
|
1208
|
+
removeProfileChangeListener();
|
|
1209
|
+
middlewareChangeListeners.forEach(removeListener => removeListener());
|
|
1210
|
+
};
|
|
1035
1211
|
};
|
|
1036
1212
|
this.onIsInitialized = onIsInitializedCallback => {
|
|
1037
1213
|
if (typeof onIsInitializedCallback === 'function') {
|
|
@@ -1343,4 +1519,4 @@ const selectVariant = (baseline, variants, {
|
|
|
1343
1519
|
};
|
|
1344
1520
|
};
|
|
1345
1521
|
|
|
1346
|
-
export { ANONYMOUS_ID, CHANGES_FALLBACK_CACHE, COMPONENT, COMPONENT_START, CONSENT, DEBUG_FLAG, EMPTY_MERGE_ID, EXPERIENCES_FALLBACK_CACHE, EventBuilder, HAS_SEEN_STICKY_COMPONENT, LEGACY_ANONYMOUS_ID, Ninetailed, NinetailedCorePlugin, OnChangeEmitter, PAGE_HIDDEN, PLUGIN_NAME, PROFILE_CHANGE, PROFILE_FALLBACK_CACHE, PROFILE_RESET, SET_ENABLED_FEATURES, buildClientNinetailedRequestContext, decodeExperienceVariantsMap, makeExperienceSelectMiddleware, selectPluginsHavingExperienceSelectionMiddleware, selectPluginsHavingOnChangeEmitter, selectVariant };
|
|
1522
|
+
export { ANONYMOUS_ID, CHANGES_FALLBACK_CACHE, COMPONENT, COMPONENT_START, CONSENT, DEBUG_FLAG, EMPTY_MERGE_ID, EXPERIENCES_FALLBACK_CACHE, EventBuilder, HAS_SEEN_STICKY_COMPONENT, LEGACY_ANONYMOUS_ID, Ninetailed, NinetailedCorePlugin, OnChangeEmitter, PAGE_HIDDEN, PLUGIN_NAME, PROFILE_CHANGE, PROFILE_FALLBACK_CACHE, PROFILE_RESET, SET_ENABLED_FEATURES, buildClientNinetailedRequestContext, decodeExperienceVariantsMap, makeChangesModificationMiddleware, makeExperienceSelectMiddleware, selectPluginsHavingExperienceSelectionMiddleware, selectPluginsHavingOnChangeEmitter, selectVariant };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ninetailed/experience.js",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.13.0-beta.0",
|
|
4
4
|
"description": "Ninetailed SDK for javascript",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"directory": "packages/sdks/javascript"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@ninetailed/experience.js-plugin-analytics": "7.
|
|
13
|
-
"@ninetailed/experience.js-shared": "7.
|
|
12
|
+
"@ninetailed/experience.js-plugin-analytics": "7.13.0-beta.0",
|
|
13
|
+
"@ninetailed/experience.js-shared": "7.13.0-beta.0",
|
|
14
14
|
"analytics": "0.8.1",
|
|
15
15
|
"uuid": "9.0.0"
|
|
16
16
|
},
|
package/src/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from './lib/plugins/selectPluginsHavingExperienceSelectionMiddleware';
|
|
|
8
8
|
export * from './lib/plugins/selectPluginsHavingOnChangeEmitter';
|
|
9
9
|
export * from './lib/types/interfaces/RequiresEventBuilder';
|
|
10
10
|
export * from './lib/types/interfaces/HasExperienceSelectionMiddleware';
|
|
11
|
+
export * from './lib/types/interfaces/HasChangesModificationMiddleware';
|
|
11
12
|
export * from './lib/types/interfaces/InterestedInSeenElements';
|
|
12
13
|
export * from './lib/types/interfaces/InterestedInProfileChange';
|
|
13
14
|
export * from './lib/types/interfaces/InterestedInHiddenPage';
|
package/src/lib/Ninetailed.d.ts
CHANGED
|
@@ -82,11 +82,13 @@ export declare class Ninetailed implements NinetailedInstance {
|
|
|
82
82
|
onSelectVariant: <Baseline extends Reference, Variant extends Reference>({ baseline, experiences }: OnSelectVariantArgs<Baseline, Variant>, cb: OnSelectVariantCallback<Baseline, Variant>) => () => void;
|
|
83
83
|
/**
|
|
84
84
|
* Registers a callback to be notified when changes occur in the profile state.
|
|
85
|
+
* Uses the changes modification middleware system to process changes.
|
|
86
|
+
* Changes are processed in the following order:
|
|
85
87
|
*
|
|
86
88
|
* @param cb - Callback function that receives the changes state
|
|
87
89
|
* @returns Function to unsubscribe from changes updates
|
|
88
90
|
*/
|
|
89
|
-
onChangesChange: (cb: OnChangesChangeCallback) =>
|
|
91
|
+
onChangesChange: (cb: OnChangesChangeCallback) => () => void;
|
|
90
92
|
/**
|
|
91
93
|
* Helper method to extract changes state from profile state and notify callback
|
|
92
94
|
* @private
|
|
@@ -2,3 +2,4 @@ export * from './types';
|
|
|
2
2
|
export { EXPERIENCE_TRAIT_PREFIX, selectDistribution, isExperienceMatch, selectVariant as selectExperienceVariant, selectHasVariants as selectHasExperienceVariants, selectVariants as selectExperienceVariants, selectBaselineWithVariants as selectExperienceBaselineWithVariants, selectExperience, selectActiveExperiments, } from '@ninetailed/experience.js-shared';
|
|
3
3
|
export { decodeExperienceVariantsMap } from './decodeExperienceVariantsMap';
|
|
4
4
|
export { makeExperienceSelectMiddleware } from './makeExperienceSelectMiddleware';
|
|
5
|
+
export { makeChangesModificationMiddleware } from './makeChangesModificationMiddleware';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Change } from '@ninetailed/experience.js-shared';
|
|
2
|
+
import { NinetailedPlugin } from '@ninetailed/experience.js-plugin-analytics';
|
|
3
|
+
import { ChangesModificationMiddleware } from '../types/interfaces/HasChangesModificationMiddleware';
|
|
4
|
+
/**
|
|
5
|
+
* Arguments for creating a changes modification middleware
|
|
6
|
+
*/
|
|
7
|
+
type CreateChangesModificationMiddlewareArg = {
|
|
8
|
+
plugins: NinetailedPlugin[];
|
|
9
|
+
changes: Change[];
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Arguments for making a changes modification middleware with change notification
|
|
13
|
+
*/
|
|
14
|
+
type MakeChangesModificationMiddlewareArg = CreateChangesModificationMiddlewareArg & {
|
|
15
|
+
onChange: (middleware: ChangesModificationMiddleware) => void;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Result of creating a changes modification middleware
|
|
19
|
+
*/
|
|
20
|
+
interface ChangesModificationMiddlewareResult {
|
|
21
|
+
addListeners: () => void;
|
|
22
|
+
removeListeners: () => void;
|
|
23
|
+
middleware: ChangesModificationMiddleware;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a changes modification middleware system with change notification
|
|
27
|
+
*
|
|
28
|
+
* This follows the same pattern as the experience selection middleware system
|
|
29
|
+
*/
|
|
30
|
+
export declare const makeChangesModificationMiddleware: ({ plugins, onChange, changes, }: MakeChangesModificationMiddlewareArg) => ChangesModificationMiddlewareResult;
|
|
31
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type { Reference, Baseline, VariantRef, ExperienceConfiguration,
|
|
1
|
+
export type { Reference, Baseline, VariantRef, ExperienceConfiguration, EntryReplacement, InlineVariable, Distribution, ExperienceType, } from '@ninetailed/experience.js-shared';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { HasChangesModificationMiddleware } from '../types/interfaces/HasChangesModificationMiddleware';
|
|
2
|
+
/**
|
|
3
|
+
* Type guard that checks if an object implements the HasChangesModificationMiddleware interface
|
|
4
|
+
*
|
|
5
|
+
* @param arg Object to check
|
|
6
|
+
* @returns Boolean indicating if the object implements HasChangesModificationMiddleware
|
|
7
|
+
*/
|
|
8
|
+
export declare const hasChangesModificationMiddleware: (arg: unknown) => arg is HasChangesModificationMiddleware;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NinetailedPlugin } from '@ninetailed/experience.js-plugin-analytics';
|
|
2
|
+
import { HasChangesModificationMiddleware } from '../types/interfaces/HasChangesModificationMiddleware';
|
|
3
|
+
/**
|
|
4
|
+
* Selects plugins that implement the HasChangesModificationMiddleware interface
|
|
5
|
+
*
|
|
6
|
+
* @param plugins Array of Ninetailed plugins
|
|
7
|
+
* @returns Array of plugins that implement HasChangesModificationMiddleware
|
|
8
|
+
*/
|
|
9
|
+
export declare const selectPluginsHavingChangesModificationMiddleware: (plugins: NinetailedPlugin[]) => HasChangesModificationMiddleware[];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Change } from '@ninetailed/experience.js-shared';
|
|
2
|
+
/**
|
|
3
|
+
* Arguments passed to changes modification middleware
|
|
4
|
+
*/
|
|
5
|
+
export interface ChangesModificationMiddlewareArg {
|
|
6
|
+
changes: Change[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A middleware function that can modify changes
|
|
10
|
+
*/
|
|
11
|
+
export type ChangesModificationMiddleware = (arg: ChangesModificationMiddlewareArg) => ChangesModificationMiddlewareArg;
|
|
12
|
+
/**
|
|
13
|
+
* Arguments for building a changes modification middleware
|
|
14
|
+
*/
|
|
15
|
+
export type BuildChangesModificationMiddlewareArg = {
|
|
16
|
+
changes: Change[];
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Type for a function that builds changes modification middleware
|
|
20
|
+
*/
|
|
21
|
+
export type BuildChangesModificationMiddleware = (arg: BuildChangesModificationMiddlewareArg) => ChangesModificationMiddleware | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Interface for plugins that can provide changes modification middleware
|
|
24
|
+
*/
|
|
25
|
+
export interface HasChangesModificationMiddleware {
|
|
26
|
+
/**
|
|
27
|
+
* Returns a middleware function that can modify changes
|
|
28
|
+
*/
|
|
29
|
+
getChangesModificationMiddleware: BuildChangesModificationMiddleware;
|
|
30
|
+
}
|