saltfish 0.3.36 → 0.3.37

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.
@@ -2911,6 +2911,51 @@ class PlaylistOrchestrator {
2911
2911
  destroy() {
2912
2912
  }
2913
2913
  }
2914
+ function validateUrlRequirement(urlRequirement) {
2915
+ const { pattern, matchType } = urlRequirement;
2916
+ if (!pattern) {
2917
+ return true;
2918
+ }
2919
+ const currentUrl = window.location.href;
2920
+ const currentPath = window.location.pathname;
2921
+ if (matchType === "regex") {
2922
+ try {
2923
+ const regex = new RegExp(pattern);
2924
+ const fullUrlMatch = regex.test(currentUrl);
2925
+ const pathMatch = regex.test(currentPath);
2926
+ const matches2 = fullUrlMatch || pathMatch;
2927
+ log(`urlValidation: Result (regex) - matches: ${matches2}`);
2928
+ return matches2;
2929
+ } catch (error2) {
2930
+ return false;
2931
+ }
2932
+ }
2933
+ if (matchType === "contains") {
2934
+ const matches2 = currentUrl.includes(pattern) || currentPath.includes(pattern);
2935
+ return matches2;
2936
+ }
2937
+ const matches = currentUrl === pattern || currentPath === pattern;
2938
+ return matches;
2939
+ }
2940
+ async function validateUrlRequirementWithRetry(urlRequirement, maxRetries = 20, retryDelay = 100) {
2941
+ if (!urlRequirement) {
2942
+ return true;
2943
+ }
2944
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
2945
+ if (validateUrlRequirement(urlRequirement)) {
2946
+ return true;
2947
+ }
2948
+ if (attempt < maxRetries - 1) {
2949
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
2950
+ const saltfishPlayer = window._saltfishPlayer;
2951
+ if (!saltfishPlayer) {
2952
+ return false;
2953
+ }
2954
+ }
2955
+ }
2956
+ log(`urlValidation: Expected pattern: '${urlRequirement.pattern}' (matchType: ${urlRequirement.matchType})`);
2957
+ return false;
2958
+ }
2914
2959
  class StateMachineActionHandler {
2915
2960
  constructor(managers) {
2916
2961
  __publicField(this, "managers");
@@ -3147,47 +3192,24 @@ class StateMachineActionHandler {
3147
3192
  if (!step.urlRequirement) {
3148
3193
  return true;
3149
3194
  }
3150
- const { pattern, matchType } = step.urlRequirement;
3151
- if (!pattern) {
3152
- return true;
3153
- }
3154
- const checkUrl = () => {
3155
- const currentUrl = window.location.href;
3156
- const currentPath = window.location.pathname;
3157
- let matches = false;
3158
- if (matchType === "regex") {
3159
- try {
3160
- const regex = new RegExp(pattern);
3161
- matches = regex.test(currentUrl) || regex.test(currentPath);
3162
- } catch (error2) {
3163
- }
3164
- } else if (matchType === "contains") {
3165
- matches = currentUrl.includes(pattern) || currentPath.includes(pattern);
3166
- } else {
3167
- matches = currentUrl === pattern || currentPath === pattern;
3168
- }
3169
- return matches;
3170
- };
3171
- const maxRetries = 20;
3172
- const retryDelay = 100;
3173
- for (let attempt = 0; attempt < maxRetries; attempt++) {
3174
- if (checkUrl()) {
3175
- return true;
3176
- }
3177
- if (attempt < maxRetries - 1) {
3178
- await new Promise((resolve) => setTimeout(resolve, retryDelay));
3179
- const saltfishPlayer2 = window._saltfishPlayer;
3180
- if (!saltfishPlayer2) {
3181
- return false;
3195
+ log(`StateMachineActionHandler: Validating URL requirement for step ${step.id} with retry logic`);
3196
+ this.managers.transitionManager.startStateMachineValidation();
3197
+ try {
3198
+ const isValid = await validateUrlRequirementWithRetry(step.urlRequirement);
3199
+ if (!isValid) {
3200
+ log(`StateMachineActionHandler: URL requirement validation failed for step '${step.id}'`);
3201
+ log(`StateMachineActionHandler: Exiting playlist and closing player`);
3202
+ const saltfishPlayer = window._saltfishPlayer;
3203
+ if (saltfishPlayer && typeof saltfishPlayer.destroy === "function") {
3204
+ saltfishPlayer.destroy();
3205
+ } else {
3206
+ log("StateMachineActionHandler: Warning - Could not find SaltfishPlayer instance to destroy");
3182
3207
  }
3183
3208
  }
3209
+ return isValid;
3210
+ } finally {
3211
+ this.managers.transitionManager.endStateMachineValidation();
3184
3212
  }
3185
- log(`StateMachineActionHandler: URL requirement validation failed after ${maxRetries} retries for step '${step.id}'`);
3186
- const saltfishPlayer = window._saltfishPlayer;
3187
- if (saltfishPlayer && typeof saltfishPlayer.destroy === "function") {
3188
- saltfishPlayer.destroy();
3189
- }
3190
- return false;
3191
3213
  }
3192
3214
  // Private action handler methods
3193
3215
  async handleStartVideoPlayback(context) {
@@ -8878,12 +8900,17 @@ class TransitionManager {
8878
8900
  __publicField(this, "activeTransitions", /* @__PURE__ */ new Map());
8879
8901
  // Track current transition state
8880
8902
  __publicField(this, "waitingForInteraction", false);
8903
+ // Track when StateMachineActionHandler is validating to avoid race conditions
8904
+ __publicField(this, "isStateMachineValidating", false);
8881
8905
  // Reference to TriggerManager for coordinating playlist triggers
8882
8906
  __publicField(this, "triggerManager", null);
8883
8907
  /**
8884
8908
  * Handles URL changes by checking active URL path transitions and playlist triggers
8885
8909
  */
8886
8910
  __publicField(this, "handleURLChange", () => {
8911
+ if (this.isStateMachineValidating) {
8912
+ return;
8913
+ }
8887
8914
  const urlPathTransitions = Array.from(this.activeTransitions.entries()).filter(([_, transition]) => {
8888
8915
  var _a;
8889
8916
  return ((_a = transition.data) == null ? void 0 : _a.type) === "url-path";
@@ -9156,37 +9183,6 @@ class TransitionManager {
9156
9183
  const pathMatch = regex.test(currentPath);
9157
9184
  return fullUrlMatch || pathMatch;
9158
9185
  }
9159
- /**
9160
- * Validates if the current URL matches a URL requirement
9161
- * @param urlRequirement - The URL requirement to validate against
9162
- * @returns true if URL matches, false otherwise
9163
- */
9164
- validateUrlRequirement(urlRequirement) {
9165
- const { pattern, matchType } = urlRequirement;
9166
- if (!pattern) {
9167
- return true;
9168
- }
9169
- const currentUrl = window.location.href;
9170
- const currentPath = window.location.pathname;
9171
- if (matchType === "regex") {
9172
- try {
9173
- const regex = new RegExp(pattern);
9174
- const fullUrlMatch = regex.test(currentUrl);
9175
- const pathMatch = regex.test(currentPath);
9176
- const matches2 = fullUrlMatch || pathMatch;
9177
- log(`TransitionManager: URL requirement validation (regex) - matches: ${matches2}`);
9178
- return matches2;
9179
- } catch (error2) {
9180
- return false;
9181
- }
9182
- }
9183
- if (matchType === "contains") {
9184
- const matches2 = currentUrl.includes(pattern) || currentPath.includes(pattern);
9185
- return matches2;
9186
- }
9187
- const matches = currentUrl === pattern || currentPath === pattern;
9188
- return matches;
9189
- }
9190
9186
  /**
9191
9187
  * Handles URL requirement validation failure by exiting and closing the playlist
9192
9188
  * @param stepId - The step ID that failed validation
@@ -9201,8 +9197,9 @@ class TransitionManager {
9201
9197
  }
9202
9198
  }
9203
9199
  /**
9204
- * Validates the URL requirement for the current step
9205
- * @returns true if validation passes or no requirement exists, false if validation fails
9200
+ * Validates the URL requirement for the current step (immediate, no retries)
9201
+ * Used for external navigation detection - should close immediately if URL doesn't match
9202
+ * @returns boolean - true if validation passes or no requirement exists, false if validation fails
9206
9203
  */
9207
9204
  validateCurrentStepUrl() {
9208
9205
  const store = getSaltfishStore();
@@ -9215,7 +9212,7 @@ class TransitionManager {
9215
9212
  if (!currentStep || !currentStep.urlRequirement) {
9216
9213
  return true;
9217
9214
  }
9218
- const isValid = this.validateUrlRequirement(currentStep.urlRequirement);
9215
+ const isValid = validateUrlRequirement(currentStep.urlRequirement);
9219
9216
  if (!isValid) {
9220
9217
  this.handleUrlRequirementFailure(currentStepId, currentStep.urlRequirement);
9221
9218
  }
@@ -9300,6 +9297,19 @@ class TransitionManager {
9300
9297
  reset() {
9301
9298
  this.cleanupTransitions();
9302
9299
  }
9300
+ /**
9301
+ * Marks the start of StateMachineActionHandler validation to prevent race conditions
9302
+ * TransitionManager will skip validation while this flag is set
9303
+ */
9304
+ startStateMachineValidation() {
9305
+ this.isStateMachineValidating = true;
9306
+ }
9307
+ /**
9308
+ * Marks the end of StateMachineActionHandler validation
9309
+ */
9310
+ endStateMachineValidation() {
9311
+ this.isStateMachineValidating = false;
9312
+ }
9303
9313
  /**
9304
9314
  * Destroys the transition manager and cleans up resources
9305
9315
  */
@@ -11774,7 +11784,7 @@ const SaltfishPlayer$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.de
11774
11784
  __proto__: null,
11775
11785
  SaltfishPlayer
11776
11786
  }, Symbol.toStringTag, { value: "Module" }));
11777
- const version = "0.3.36";
11787
+ const version = "0.3.37";
11778
11788
  const packageJson = {
11779
11789
  version
11780
11790
  };