@ninetailed/experience.js 7.12.0-beta.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 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
- return this.onProfileChange(profileState => {
1050
- this.notifyChangesCallback(cb, profileState);
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
- return this.onProfileChange(profileState => {
1033
- this.notifyChangesCallback(cb, profileState);
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.12.0-beta.0",
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.12.0-beta.0",
13
- "@ninetailed/experience.js-shared": "7.12.0-beta.0",
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';
@@ -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) => import("analytics").DetachListeners;
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, BaselineWithVariants, Distribution, ExperienceType, } from '@ninetailed/experience.js-shared';
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[];
@@ -1,4 +1,5 @@
1
- import { type Profile } from '@ninetailed/experience.js-shared';
1
+ import type { Profile, Change } from '@ninetailed/experience.js-shared';
2
2
  export type ProfileChangedPayload = {
3
3
  profile: Profile | null;
4
+ changes: Change[] | null;
4
5
  };
@@ -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
+ }