@mxenabled/connect-widget 2.17.9 → 2.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.es.js CHANGED
@@ -9422,7 +9422,8 @@ function institutionIsBlockedForCostReasons(institution) {
9422
9422
 
9423
9423
  const initialState$6 = {
9424
9424
  optOutOfEarlyUserRelease: false,
9425
- unavailableInstitutions: []
9425
+ unavailableInstitutions: [],
9426
+ memberPollingMilliseconds: void 0
9426
9427
  };
9427
9428
  const experimentalFeaturesSlice = createSlice({
9428
9429
  name: "experimentalFeatures",
@@ -9431,6 +9432,7 @@ const experimentalFeaturesSlice = createSlice({
9431
9432
  loadExperimentalFeatures(state, action) {
9432
9433
  state.unavailableInstitutions = action.payload?.unavailableInstitutions || [];
9433
9434
  state.optOutOfEarlyUserRelease = action.payload?.optOutOfEarlyUserRelease || false;
9435
+ state.memberPollingMilliseconds = action.payload?.memberPollingMilliseconds || void 0;
9434
9436
  }
9435
9437
  }
9436
9438
  });
@@ -64055,6 +64057,26 @@ function delay$1(due, scheduler) {
64055
64057
  });
64056
64058
  }
64057
64059
 
64060
+ function exhaustMap(project, resultSelector) {
64061
+ return operate(function(source, subscriber) {
64062
+ var index = 0;
64063
+ var innerSub = null;
64064
+ var isComplete = false;
64065
+ source.subscribe(createOperatorSubscriber(subscriber, function(outerValue) {
64066
+ if (!innerSub) {
64067
+ innerSub = createOperatorSubscriber(subscriber, void 0, function() {
64068
+ innerSub = null;
64069
+ isComplete && subscriber.complete();
64070
+ });
64071
+ innerFrom(project(outerValue, index++)).subscribe(innerSub);
64072
+ }
64073
+ }, function() {
64074
+ isComplete = true;
64075
+ !innerSub && subscriber.complete();
64076
+ }));
64077
+ });
64078
+ }
64079
+
64058
64080
  function pluck() {
64059
64081
  var properties = [];
64060
64082
  for (var _i = 0; _i < arguments.length; _i++) {
@@ -76184,52 +76206,6 @@ const DEFAULT_POLLING_STATE = {
76184
76206
  initialDataReady: false
76185
76207
  // whether the initial data ready event has been sent
76186
76208
  };
76187
- function pollMember(memberGuid, api, clientLocale, optOutOfEarlyUserRelease = false) {
76188
- return interval(3e3).pipe(
76189
- switchMap(
76190
- () => (
76191
- // Poll the currentMember. Catch errors but don't handle it here
76192
- // the scan will handle it below
76193
- defer(() => api.loadMemberByGuid(memberGuid, clientLocale)).pipe(
76194
- mergeMap(
76195
- (member) => defer(() => api.loadJob(member.most_recent_job_guid)).pipe(
76196
- map((job) => ({ member, job }))
76197
- )
76198
- ),
76199
- catchError((error) => of(error))
76200
- )
76201
- )
76202
- ),
76203
- scan(
76204
- (acc, response) => {
76205
- const isError = response instanceof Error;
76206
- const pollingState = {
76207
- // only track if the most recent poll was an error
76208
- isError,
76209
- // always increase polling count
76210
- pollingCount: acc.pollingCount + 1,
76211
- // dont update previous response if this is an error
76212
- previousResponse: isError ? acc.previousResponse : acc.currentResponse,
76213
- // dont update current response if this is an error
76214
- currentResponse: isError ? acc.currentResponse : response,
76215
- // preserve the initialDataReadySent flag
76216
- initialDataReady: acc.initialDataReady
76217
- };
76218
- if (!isError && !acc.initialDataReady && response?.job?.async_account_data_ready && !optOutOfEarlyUserRelease) {
76219
- pollingState.initialDataReady = true;
76220
- }
76221
- const [shouldStopPolling, messageKey] = handlePollingResponse(pollingState);
76222
- return {
76223
- ...pollingState,
76224
- // we should keep polling based on the member
76225
- pollingIsDone: isError ? false : shouldStopPolling,
76226
- userMessage: messageKey
76227
- };
76228
- },
76229
- { ...DEFAULT_POLLING_STATE }
76230
- )
76231
- );
76232
- }
76233
76209
  function handlePollingResponse(pollingState) {
76234
76210
  const polledMember = pollingState.currentResponse?.member || {};
76235
76211
  const previousMember = pollingState.previousResponse?.member || {};
@@ -76264,7 +76240,14 @@ function handlePollingResponse(pollingState) {
76264
76240
  }
76265
76241
  function pollOauthState(oauthStateGuid, api) {
76266
76242
  return interval(1e3).pipe(
76267
- switchMap(
76243
+ /**
76244
+ * used to be switchMap
76245
+ * exhaustMap ignores new emissions from the source while the current inner observable is still active.
76246
+ *
76247
+ * This ensures that we do not start a new poll request until the previous one has completed,
76248
+ * preventing overlapping requests and potential race conditions.
76249
+ */
76250
+ exhaustMap(
76268
76251
  () => (
76269
76252
  // Poll the oauthstate. Catch errors but don't handle it here
76270
76253
  // the scan will handle it below
@@ -78737,6 +78720,70 @@ function getReferrer() {
78737
78720
  }
78738
78721
  const isValidUrl = (url) => typeof url === "string" && url.match(/((\w+:\/\/)[-a-zA-Z0-9:@;?&=/%+.*!'(),$_{}^~[\]`#|]+)/g);
78739
78722
 
78723
+ function usePollMember() {
78724
+ const { api } = useApi();
78725
+ const clientLocale = useMemo(() => {
78726
+ return document.querySelector("html")?.getAttribute("lang") || "en";
78727
+ }, [document.querySelector("html")?.getAttribute("lang")]);
78728
+ const { optOutOfEarlyUserRelease, memberPollingMilliseconds } = useSelector(getExperimentalFeatures);
78729
+ const pollingInterval = memberPollingMilliseconds || 3e3;
78730
+ const pollMember = (memberGuid) => {
78731
+ return interval(pollingInterval).pipe(
78732
+ /**
78733
+ * used to be switchMap
78734
+ * exhaustMap ignores new emissions from the source while the current inner observable is still active.
78735
+ *
78736
+ * This ensures that we do not start a new poll request until the previous one has completed,
78737
+ * preventing overlapping requests and potential race conditions.
78738
+ */
78739
+ exhaustMap(
78740
+ () => (
78741
+ // Poll the currentMember. Catch errors but don't handle it here
78742
+ // the scan will handle it below
78743
+ // @ts-expect-error: cannot invoke a method that might be undefined
78744
+ defer(() => api.loadMemberByGuid(memberGuid, clientLocale)).pipe(
78745
+ mergeMap(
78746
+ (member) => defer(() => api.loadJob(member.most_recent_job_guid)).pipe(
78747
+ map((job) => ({ member, job }))
78748
+ )
78749
+ ),
78750
+ catchError((error) => of(error))
78751
+ )
78752
+ )
78753
+ ),
78754
+ scan(
78755
+ (acc, response) => {
78756
+ const isError = response instanceof Error;
78757
+ const pollingState = {
78758
+ // only track if the most recent poll was an error
78759
+ isError,
78760
+ // always increase polling count
78761
+ pollingCount: acc.pollingCount + 1,
78762
+ // dont update previous response if this is an error
78763
+ previousResponse: isError ? acc.previousResponse : acc.currentResponse,
78764
+ // dont update current response if this is an error
78765
+ currentResponse: isError ? acc.currentResponse : response,
78766
+ // preserve the initialDataReadySent flag
78767
+ initialDataReady: acc.initialDataReady
78768
+ };
78769
+ if (!isError && !acc.initialDataReady && response?.job?.async_account_data_ready && !optOutOfEarlyUserRelease) {
78770
+ pollingState.initialDataReady = true;
78771
+ }
78772
+ const [shouldStopPolling, messageKey] = handlePollingResponse(pollingState);
78773
+ return {
78774
+ ...pollingState,
78775
+ // we should keep polling based on the member
78776
+ pollingIsDone: isError ? false : shouldStopPolling,
78777
+ userMessage: messageKey
78778
+ };
78779
+ },
78780
+ { ...DEFAULT_POLLING_STATE }
78781
+ )
78782
+ );
78783
+ };
78784
+ return pollMember;
78785
+ }
78786
+
78740
78787
  const Connecting = (props) => {
78741
78788
  const {
78742
78789
  connectConfig,
@@ -78747,7 +78794,6 @@ const Connecting = (props) => {
78747
78794
  onUpsertMember
78748
78795
  } = props;
78749
78796
  const selectedInstitution = useSelector(getSelectedInstitution);
78750
- const { optOutOfEarlyUserRelease } = useSelector(getExperimentalFeatures);
78751
78797
  const sendAnalyticsEvent = useAnalyticsEvent();
78752
78798
  const clientLocale = useMemo(() => {
78753
78799
  return document.querySelector("html")?.getAttribute("lang") || "en";
@@ -78769,6 +78815,7 @@ const Connecting = (props) => {
78769
78815
  const [message, setMessage] = useState(CONNECTING_MESSAGES.STARTING);
78770
78816
  const [timedOut, setTimedOut] = useState(false);
78771
78817
  const [connectingError, setConnectingError] = useState(null);
78818
+ const pollMember = usePollMember();
78772
78819
  const activeJob = getActiveJob(jobSchedule);
78773
78820
  const needsToInitializeJobSchedule = jobSchedule.isInitialized === false;
78774
78821
  function handleMemberPoll(pollingState) {
@@ -78898,7 +78945,7 @@ const Connecting = (props) => {
78898
78945
  return needsJobStarted ? startJob$ : of(currentMember);
78899
78946
  }).pipe(
78900
78947
  concatMap(
78901
- (member) => pollMember(member.guid, api, clientLocale, optOutOfEarlyUserRelease).pipe(
78948
+ (member) => pollMember(member.guid).pipe(
78902
78949
  tap((pollingState) => handleMemberPoll(pollingState)),
78903
78950
  filter((pollingState) => pollingState.pollingIsDone),
78904
78951
  pluck("currentResponse"),
@@ -82680,6 +82727,8 @@ const getStyles$h = (tokens) => ({
82680
82727
  position: "relative"
82681
82728
  },
82682
82729
  svg: {
82730
+ display: "flex",
82731
+ alignItems: "center",
82683
82732
  margin: "0 auto",
82684
82733
  width: 200
82685
82734
  },