@funnelsgrove/runtime 0.1.48 → 0.1.49

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.
@@ -10,4 +10,5 @@ export type Assignment = {
10
10
  variantKey: string;
11
11
  routeToStepId: string;
12
12
  };
13
+ export declare const resolveForcedExperimentAssignment: (input: ResolveInput) => Assignment | null;
13
14
  export declare const resolveExperimentAssignment: (input: ResolveInput) => Assignment | null;
@@ -16,14 +16,21 @@ const resolveForcedVariant = (input) => {
16
16
  return null;
17
17
  }
18
18
  };
19
+ export const resolveForcedExperimentAssignment = (input) => {
20
+ const forcedVariant = resolveForcedVariant(input);
21
+ if (!forcedVariant) {
22
+ return null;
23
+ }
24
+ return { variantKey: forcedVariant.variantKey, routeToStepId: forcedVariant.routeToStepId };
25
+ };
19
26
  export const resolveExperimentAssignment = (input) => {
20
27
  var _a;
21
28
  if (input.variants.length === 0) {
22
29
  return null;
23
30
  }
24
- const forcedVariant = resolveForcedVariant(input);
25
- if (forcedVariant) {
26
- return { variantKey: forcedVariant.variantKey, routeToStepId: forcedVariant.routeToStepId };
31
+ const forcedAssignment = resolveForcedExperimentAssignment(input);
32
+ if (forcedAssignment) {
33
+ return forcedAssignment;
27
34
  }
28
35
  const resolved = resolveExperimentVariant(input.experimentId);
29
36
  const match = resolved ? input.variants.find((variant) => variant.variantKey === resolved) : undefined;
@@ -116,8 +116,15 @@ export declare function computeRenderSuspended(input: {
116
116
  postHogReady: boolean;
117
117
  experiments: ReadonlyArray<{
118
118
  stepId: string;
119
- }>;
119
+ } & Partial<Pick<FunnelManifestExperiment, 'experimentId' | 'variants'>>>;
120
120
  isPreviewRuntime?: boolean;
121
121
  }): boolean;
122
+ export declare function resolveRenderedExperimentStepId(input: {
123
+ activeExperiment: FunnelManifestExperiment | null;
124
+ editorVariantOverrides: Record<string, string>;
125
+ postHogReady: boolean;
126
+ resolveRenderableStepId: (stepId: string | null | undefined) => string | null;
127
+ safeActiveStepId: string;
128
+ }): string;
122
129
  export declare function useFunnelFlowController<StepId extends string>({ analytics, initialStepId, initialAttributes, lockToInitialStep, defaultStepId, stepSequence, stepById, stepComponentById, funnelExperiments, getPathForStep, getStepIdFromPath, getSequentialNextStepId, getChoiceTargetsForStep, isFunnelStepId, resolveConfiguredNextStep, resolveRuntimeInitialStepId, }: UseFunnelFlowControllerInput<StepId>): UseFunnelFlowControllerResult<StepId>;
123
130
  export {};
@@ -7,7 +7,7 @@ import { FUNNEL_ID, POSTHOG_API_HOST, POSTHOG_PROJECT_API_KEY, PROJECT_ID, } fro
7
7
  import { buildHostedStepLocation, dispatchWindowCustomEvent, } from './browser-helpers.js';
8
8
  import { isPreviewStepLockRequested, resolveNextStepFromContext, shouldRunAutoAdvanceTimer, } from './funnel-flow.js';
9
9
  import { usePreviewBridge } from './preview-bridge.js';
10
- import { resolveExperimentAssignment } from './experiment-assignment.js';
10
+ import { resolveExperimentAssignment, resolveForcedExperimentAssignment, } from './experiment-assignment.js';
11
11
  import { collectCurrentFunnelAttribution } from './funnel-attribution.js';
12
12
  import { resolveUrlUserAttributes } from './url-user-attributes.js';
13
13
  import { bootstrapPostHog, identifyPostHog, isPostHogReady, resolveExperimentVariant, } from './posthog-flags.js';
@@ -15,10 +15,56 @@ import { getRuntimeMode, isEditorEnabled, useRuntimeMode } from '../services/run
15
15
  import { isPreviewFrameRuntime } from '../services/preview-frame.service.js';
16
16
  const FIRST_STEP_ENGAGEMENT_THRESHOLD_MS = 1000;
17
17
  export function computeRenderSuspended(input) {
18
+ var _a;
18
19
  if (input.isPreviewRuntime || input.postHogReady) {
19
20
  return false;
20
21
  }
21
- return input.experiments.some((experiment) => experiment.stepId === input.activeStepId);
22
+ const activeExperiment = input.experiments.find((experiment) => experiment.stepId === input.activeStepId);
23
+ if (!activeExperiment) {
24
+ return false;
25
+ }
26
+ if (activeExperiment.experimentId && ((_a = activeExperiment.variants) === null || _a === void 0 ? void 0 : _a.length)) {
27
+ const forcedAssignment = resolveForcedExperimentAssignment({
28
+ experimentId: activeExperiment.experimentId,
29
+ variants: activeExperiment.variants,
30
+ });
31
+ if (forcedAssignment) {
32
+ return false;
33
+ }
34
+ }
35
+ return true;
36
+ }
37
+ export function resolveRenderedExperimentStepId(input) {
38
+ const { activeExperiment, editorVariantOverrides, postHogReady, resolveRenderableStepId, safeActiveStepId, } = input;
39
+ if (!activeExperiment) {
40
+ return safeActiveStepId;
41
+ }
42
+ const override = editorVariantOverrides[activeExperiment.experimentId];
43
+ if (override) {
44
+ const matchedVariant = activeExperiment.variants.find((variant) => variant.variantKey === override);
45
+ const variantStepId = resolveRenderableStepId((matchedVariant === null || matchedVariant === void 0 ? void 0 : matchedVariant.routeToStepId) || null);
46
+ return variantStepId !== null && variantStepId !== void 0 ? variantStepId : safeActiveStepId;
47
+ }
48
+ const forcedAssignment = resolveForcedExperimentAssignment({
49
+ experimentId: activeExperiment.experimentId,
50
+ variants: activeExperiment.variants,
51
+ });
52
+ if (forcedAssignment) {
53
+ const forcedStepId = resolveRenderableStepId(forcedAssignment.routeToStepId);
54
+ return forcedStepId !== null && forcedStepId !== void 0 ? forcedStepId : safeActiveStepId;
55
+ }
56
+ if (!postHogReady) {
57
+ return safeActiveStepId;
58
+ }
59
+ const assignment = resolveExperimentAssignment({
60
+ experimentId: activeExperiment.experimentId,
61
+ variants: activeExperiment.variants,
62
+ });
63
+ if (!assignment) {
64
+ return safeActiveStepId;
65
+ }
66
+ const variantStepId = resolveRenderableStepId(assignment.routeToStepId);
67
+ return variantStepId !== null && variantStepId !== void 0 ? variantStepId : safeActiveStepId;
22
68
  }
23
69
  export function useFunnelFlowController({ analytics, initialStepId, initialAttributes, lockToInitialStep = false, defaultStepId, stepSequence, stepById, stepComponentById, funnelExperiments, getPathForStep, getStepIdFromPath, getSequentialNextStepId, getChoiceTargetsForStep, isFunnelStepId, resolveConfiguredNextStep, resolveRuntimeInitialStepId, }) {
24
70
  var _a, _b;
@@ -92,35 +138,26 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
92
138
  if (override) {
93
139
  return override;
94
140
  }
141
+ const forcedAssignment = resolveForcedExperimentAssignment({
142
+ experimentId: experiment.experimentId,
143
+ variants: experiment.variants,
144
+ });
145
+ if (forcedAssignment) {
146
+ return forcedAssignment.variantKey;
147
+ }
95
148
  if (!postHogReady) {
96
149
  return null;
97
150
  }
98
151
  return (_a = resolveExperimentVariant(experiment.experimentId)) !== null && _a !== void 0 ? _a : null;
99
152
  }, [editorVariantOverrides, postHogReady]);
100
153
  const activeExperimentForStep = useMemo(() => funnelExperiments.find((candidate) => candidate.stepId === safeActiveStepId) || null, [funnelExperiments, safeActiveStepId]);
101
- const renderedStepId = useMemo(() => {
102
- if (!activeExperimentForStep) {
103
- return safeActiveStepId;
104
- }
105
- const override = editorVariantOverrides[activeExperimentForStep.experimentId];
106
- if (override) {
107
- const matchedVariant = activeExperimentForStep.variants.find((variant) => variant.variantKey === override);
108
- const variantStepId = resolveRenderableStepId((matchedVariant === null || matchedVariant === void 0 ? void 0 : matchedVariant.routeToStepId) || null);
109
- return variantStepId !== null && variantStepId !== void 0 ? variantStepId : safeActiveStepId;
110
- }
111
- if (!postHogReady) {
112
- return safeActiveStepId;
113
- }
114
- const assignment = resolveExperimentAssignment({
115
- experimentId: activeExperimentForStep.experimentId,
116
- variants: activeExperimentForStep.variants,
117
- });
118
- if (!assignment) {
119
- return safeActiveStepId;
120
- }
121
- const variantStepId = resolveRenderableStepId(assignment.routeToStepId);
122
- return variantStepId !== null && variantStepId !== void 0 ? variantStepId : safeActiveStepId;
123
- }, [activeExperimentForStep, editorVariantOverrides, postHogReady, resolveRenderableStepId, safeActiveStepId]);
154
+ const renderedStepId = useMemo(() => resolveRenderedExperimentStepId({
155
+ activeExperiment: activeExperimentForStep,
156
+ editorVariantOverrides,
157
+ postHogReady,
158
+ resolveRenderableStepId,
159
+ safeActiveStepId,
160
+ }), [activeExperimentForStep, editorVariantOverrides, postHogReady, resolveRenderableStepId, safeActiveStepId]);
124
161
  const renderedStepMeta = stepById[renderedStepId];
125
162
  const activeStepComponent = stepComponentById[renderedStepId];
126
163
  const postHogFeatureFlags = useMemo(() => {
@@ -584,6 +621,13 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
584
621
  if (override) {
585
622
  return override;
586
623
  }
624
+ const forcedAssignment = resolveForcedExperimentAssignment({
625
+ experimentId: experiment.experimentId,
626
+ variants: experiment.variants,
627
+ });
628
+ if (forcedAssignment) {
629
+ return forcedAssignment.variantKey;
630
+ }
587
631
  if (postHogReady) {
588
632
  const assignment = resolveExperimentAssignment({
589
633
  experimentId: experiment.experimentId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/runtime",
3
- "version": "0.1.48",
3
+ "version": "0.1.49",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "main": "./dist/index.js",