@funnelsgrove/runtime 0.7.14 → 0.7.16

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.
@@ -7,8 +7,6 @@ export declare const RUNTIME_ENV_KEYS: {
7
7
  readonly projectId: "NEXT_PUBLIC_PROJECT_ID";
8
8
  readonly funnelVersionId: "NEXT_PUBLIC_FUNNEL_VERSION_ID";
9
9
  readonly posthogProjectApiKey: "NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY";
10
- readonly posthogSessionReplayEnabled: "NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED";
11
- readonly posthogSessionReplaySampleRate: "NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE";
12
10
  readonly supportEmail: "NEXT_PUBLIC_FUNNEL_SUPPORT_EMAIL";
13
11
  readonly iosAppStoreUrl: "NEXT_PUBLIC_IOS_APP_STORE_URL";
14
12
  readonly androidPlayStoreUrl: "NEXT_PUBLIC_ANDROID_PLAY_STORE_URL";
@@ -18,8 +18,6 @@ export const RUNTIME_ENV_KEYS = {
18
18
  projectId: 'NEXT_PUBLIC_PROJECT_ID',
19
19
  funnelVersionId: 'NEXT_PUBLIC_FUNNEL_VERSION_ID',
20
20
  posthogProjectApiKey: 'NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY',
21
- posthogSessionReplayEnabled: 'NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED',
22
- posthogSessionReplaySampleRate: 'NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE',
23
21
  supportEmail: 'NEXT_PUBLIC_FUNNEL_SUPPORT_EMAIL',
24
22
  iosAppStoreUrl: 'NEXT_PUBLIC_IOS_APP_STORE_URL',
25
23
  androidPlayStoreUrl: 'NEXT_PUBLIC_ANDROID_PLAY_STORE_URL',
@@ -81,8 +79,6 @@ const RUNTIME_ENV_VALUES = {
81
79
  NEXT_PUBLIC_FUNNEL_VERSION_ID: readRuntimeEnv(() => process.env.NEXT_PUBLIC_FUNNEL_VERSION_ID),
82
80
  NEXT_PUBLIC_PROJECT_ID: readRuntimeEnv(() => process.env.NEXT_PUBLIC_PROJECT_ID),
83
81
  NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY: readRuntimeEnv(() => process.env.NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY),
84
- NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED: readRuntimeEnv(() => process.env.NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED),
85
- NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE: readRuntimeEnv(() => process.env.NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE),
86
82
  NEXT_PUBLIC_FUNNEL_SUPPORT_EMAIL: readRuntimeEnv(() => process.env.NEXT_PUBLIC_FUNNEL_SUPPORT_EMAIL),
87
83
  NEXT_PUBLIC_IOS_APP_STORE_URL: readRuntimeEnv(() => process.env.NEXT_PUBLIC_IOS_APP_STORE_URL),
88
84
  NEXT_PUBLIC_ANDROID_PLAY_STORE_URL: readRuntimeEnv(() => process.env.NEXT_PUBLIC_ANDROID_PLAY_STORE_URL),
@@ -8,6 +8,10 @@ type BootstrapConfig = {
8
8
  distinctId: string;
9
9
  projectId?: string;
10
10
  funnelId?: string;
11
+ sessionReplay?: {
12
+ enabled: boolean;
13
+ sampleRate: number;
14
+ };
11
15
  };
12
16
  export declare const bootstrapPostHog: (config: BootstrapConfig) => Promise<void>;
13
17
  export declare const isPostHogReady: () => boolean;
@@ -68,6 +68,7 @@ export const bootstrapPostHog = (config) => {
68
68
  return readyPromise;
69
69
  }
70
70
  readyPromise = new Promise((resolve) => {
71
+ var _a;
71
72
  if (!config.apiKey || !config.apiHost) {
72
73
  resolve();
73
74
  return;
@@ -85,8 +86,8 @@ export const bootstrapPostHog = (config) => {
85
86
  };
86
87
  readyTimeoutId = setTimeout(markReady, POSTHOG_FEATURE_FLAG_READY_TIMEOUT_MS);
87
88
  const scopeProperties = buildFlagScopeProperties(config);
88
- const sessionReplayEnabled = runtimePublicConfig.posthogSessionReplayEnabled
89
- && shouldRecordPostHogSession(config.distinctId, runtimePublicConfig.posthogSessionReplaySampleRate);
89
+ const sessionReplayEnabled = ((_a = config.sessionReplay) === null || _a === void 0 ? void 0 : _a.enabled) === true
90
+ && shouldRecordPostHogSession(config.distinctId, config.sessionReplay.sampleRate);
90
91
  primePostHogFlagScopePersistence(config.apiKey, scopeProperties);
91
92
  posthog.init(config.apiKey, {
92
93
  api_host: config.apiHost,
@@ -118,6 +118,10 @@ type UseFunnelFlowControllerInput<StepId extends string> = {
118
118
  stepById: Record<string, FunnelStepMeta>;
119
119
  stepComponentById: StepComponentRegistry;
120
120
  funnelExperiments: readonly FunnelFlowControllerExperiment<StepId>[];
121
+ sessionReplay?: {
122
+ enabled: boolean;
123
+ sampleRate: number;
124
+ };
121
125
  getPathForStep: (stepId: StepId) => string;
122
126
  getStepIdFromPath: (pathname: string) => StepId | null;
123
127
  getSequentialNextStepId: (stepId: StepId) => StepId | null;
@@ -179,5 +183,5 @@ export declare function resolveRenderedExperimentStepId(input: {
179
183
  resolveRenderableStepId: (stepId: string | null | undefined) => string | null;
180
184
  safeActiveStepId: string;
181
185
  }): string;
182
- export declare function useFunnelFlowController<StepId extends string>({ api, analytics, stepContractVersion, initialStepId, initialAttributes, lockToInitialStep, defaultStepId, stepSequence, stepById, stepComponentById, funnelExperiments, getPathForStep, getStepIdFromPath, getSequentialNextStepId, getChoiceTargetsForStep, isFunnelStepId, resolveConfiguredNextStep, resolveRuntimeInitialStepId, }: UseFunnelFlowControllerInput<StepId>): UseFunnelFlowControllerResult<StepId>;
186
+ export declare function useFunnelFlowController<StepId extends string>({ api, analytics, stepContractVersion, initialStepId, initialAttributes, lockToInitialStep, defaultStepId, stepSequence, stepById, stepComponentById, funnelExperiments, sessionReplay, getPathForStep, getStepIdFromPath, getSequentialNextStepId, getChoiceTargetsForStep, isFunnelStepId, resolveConfiguredNextStep, resolveRuntimeInitialStepId, }: UseFunnelFlowControllerInput<StepId>): UseFunnelFlowControllerResult<StepId>;
183
187
  export {};
@@ -278,7 +278,7 @@ export function resolveRenderedExperimentStepId(input) {
278
278
  const variantStepId = resolveRenderableStepId(assignment.routeToStepId);
279
279
  return variantStepId !== null && variantStepId !== void 0 ? variantStepId : safeActiveStepId;
280
280
  }
281
- export function useFunnelFlowController({ api = apiService, analytics, stepContractVersion, initialStepId, initialAttributes, lockToInitialStep = false, defaultStepId, stepSequence, stepById, stepComponentById, funnelExperiments, getPathForStep, getStepIdFromPath, getSequentialNextStepId, getChoiceTargetsForStep, isFunnelStepId, resolveConfiguredNextStep, resolveRuntimeInitialStepId, }) {
281
+ export function useFunnelFlowController({ api = apiService, analytics, stepContractVersion, initialStepId, initialAttributes, lockToInitialStep = false, defaultStepId, stepSequence, stepById, stepComponentById, funnelExperiments, sessionReplay, getPathForStep, getStepIdFromPath, getSequentialNextStepId, getChoiceTargetsForStep, isFunnelStepId, resolveConfiguredNextStep, resolveRuntimeInitialStepId, }) {
282
282
  var _a, _b, _c;
283
283
  const [runtimeMode] = useRuntimeMode();
284
284
  const [editorModeEnabled, setEditorModeEnabled] = useState(() => isEditorEnabled());
@@ -287,6 +287,8 @@ export function useFunnelFlowController({ api = apiService, analytics, stepContr
287
287
  const [editorVariantOverrides, setEditorVariantOverrides] = useState({});
288
288
  const shouldLockToInitialStep = lockToInitialStep || isPreviewStepLockRequested();
289
289
  const isPreviewRuntime = useMemo(() => isPreviewFrameRuntime(), []);
290
+ const sessionReplayEnabled = sessionReplay === null || sessionReplay === void 0 ? void 0 : sessionReplay.enabled;
291
+ const sessionReplaySampleRate = sessionReplay === null || sessionReplay === void 0 ? void 0 : sessionReplay.sampleRate;
290
292
  const resolveRenderableStepId = useCallback((stepId) => {
291
293
  if (!stepId || !isFunnelStepId(stepId)) {
292
294
  return null;
@@ -540,6 +542,12 @@ export function useFunnelFlowController({ api = apiService, analytics, stepContr
540
542
  distinctId: localUserId,
541
543
  projectId: PROJECT_ID,
542
544
  funnelId: FUNNEL_ID,
545
+ sessionReplay: sessionReplayEnabled !== undefined && sessionReplaySampleRate !== undefined
546
+ ? {
547
+ enabled: sessionReplayEnabled,
548
+ sampleRate: sessionReplaySampleRate,
549
+ }
550
+ : undefined,
543
551
  })
544
552
  .then(() => setPostHogReady(true))
545
553
  .catch((error) => {
@@ -598,7 +606,13 @@ export function useFunnelFlowController({ api = apiService, analytics, stepContr
598
606
  logger.error('Failed to identify PostHog user:', error);
599
607
  });
600
608
  return cancelAttributionFailOpen;
601
- }, [api, isPreviewRuntime, isSubscriptionManagementRuntime]);
609
+ }, [
610
+ api,
611
+ isPreviewRuntime,
612
+ isSubscriptionManagementRuntime,
613
+ sessionReplayEnabled,
614
+ sessionReplaySampleRate,
615
+ ]);
602
616
  const recordStepCompletion = useCallback((intent, options = {}) => {
603
617
  var _a;
604
618
  const meta = stepById[intent.visit.stepId];
@@ -4,14 +4,25 @@ export type FunnelRuntimeConfig = {
4
4
  schemaVersion: 2;
5
5
  funnelId: string;
6
6
  projectId: string;
7
+ sessionReplay?: {
8
+ enabled?: unknown;
9
+ sampleRate?: unknown;
10
+ };
11
+ defaultOfferSetId?: string | null;
7
12
  offerSets: unknown[];
8
13
  experiments: unknown[];
9
14
  };
15
+ export type FunnelSessionReplayConfig = {
16
+ enabled: boolean;
17
+ sampleRate: number;
18
+ };
10
19
  export type ResolvedFunnelRuntimeConfig = {
11
20
  revisionId: string;
12
21
  sourceDeploymentId: string;
13
22
  sourceVersionId: string;
14
23
  publishedAt: string;
24
+ sessionReplay?: FunnelSessionReplayConfig;
25
+ defaultOfferSetId?: string | null;
15
26
  offerSets: readonly GeneratedOfferSet[];
16
27
  experiments: readonly FunnelExperimentDefinition[];
17
28
  };
@@ -26,6 +26,19 @@ const pick = (record, ...keys) => {
26
26
  const pickString = (record, ...keys) => (readString(pick(record, ...keys)));
27
27
  const pickNumber = (record, ...keys) => (readNumber(pick(record, ...keys)));
28
28
  const pickBoolean = (record, ...keys) => (readBoolean(pick(record, ...keys)));
29
+ const normalizeSessionReplay = (value) => {
30
+ var _a;
31
+ if (!isRecord(value)) {
32
+ return { enabled: false, sampleRate: 10 };
33
+ }
34
+ const sampleRate = readNumber(value.sampleRate);
35
+ return {
36
+ enabled: (_a = readBoolean(value.enabled)) !== null && _a !== void 0 ? _a : false,
37
+ sampleRate: sampleRate === null
38
+ ? 10
39
+ : Math.min(100, Math.max(1, Math.round(sampleRate))),
40
+ };
41
+ };
29
42
  const deepFreeze = (value) => {
30
43
  if (!value || typeof value !== 'object' || Object.isFrozen(value)) {
31
44
  return value;
@@ -234,6 +247,8 @@ export const resolvePublishedFunnelRuntimeConfig = (published, options = {}) =>
234
247
  sourceDeploymentId: published.sourceDeploymentId,
235
248
  sourceVersionId: published.sourceVersionId,
236
249
  publishedAt: published.publishedAt,
250
+ sessionReplay: normalizeSessionReplay(published.config.sessionReplay),
251
+ defaultOfferSetId: readString(published.config.defaultOfferSetId),
237
252
  offerSets,
238
253
  experiments: normalizePublishedExperiments(published.config, published.publishedAt, offerSets),
239
254
  });
@@ -4,8 +4,6 @@ export declare const PROJECT_ENV_STANDARD_KEYS: {
4
4
  readonly funnelVersionId: "NEXT_PUBLIC_FUNNEL_VERSION_ID";
5
5
  readonly projectId: "NEXT_PUBLIC_PROJECT_ID";
6
6
  readonly posthogProjectApiKey: "NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY";
7
- readonly posthogSessionReplayEnabled: "NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED";
8
- readonly posthogSessionReplaySampleRate: "NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE";
9
7
  readonly stripeEnabled: "STRIPE_ENABLED";
10
8
  readonly stripeActiveMode: "NEXT_PUBLIC_STRIPE_ACTIVE_MODE";
11
9
  readonly stripeTestPublishableKey: "NEXT_PUBLIC_STRIPE_TEST_PUBLISHABLE_KEY";
@@ -4,8 +4,6 @@ export const PROJECT_ENV_STANDARD_KEYS = {
4
4
  funnelVersionId: 'NEXT_PUBLIC_FUNNEL_VERSION_ID',
5
5
  projectId: 'NEXT_PUBLIC_PROJECT_ID',
6
6
  posthogProjectApiKey: 'NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY',
7
- posthogSessionReplayEnabled: 'NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED',
8
- posthogSessionReplaySampleRate: 'NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE',
9
7
  stripeEnabled: 'STRIPE_ENABLED',
10
8
  stripeActiveMode: 'NEXT_PUBLIC_STRIPE_ACTIVE_MODE',
11
9
  stripeTestPublishableKey: 'NEXT_PUBLIC_STRIPE_TEST_PUBLISHABLE_KEY',
@@ -80,8 +78,6 @@ const buildProjectStandardValues = (envMap) => {
80
78
  funnelVersionId: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.funnelVersionId),
81
79
  projectId: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.projectId),
82
80
  posthogProjectApiKey: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.posthogProjectApiKey),
83
- posthogSessionReplayEnabled: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.posthogSessionReplayEnabled),
84
- posthogSessionReplaySampleRate: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.posthogSessionReplaySampleRate),
85
81
  stripeEnabled: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.stripeEnabled),
86
82
  stripeActiveMode: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.stripeActiveMode),
87
83
  stripeTestPublishableKey: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.stripeTestPublishableKey),
@@ -7,8 +7,6 @@ export declare const RUNTIME_PUBLIC_ENV_KEYS: {
7
7
  readonly funnelVersionId: "NEXT_PUBLIC_FUNNEL_VERSION_ID";
8
8
  readonly projectId: "NEXT_PUBLIC_PROJECT_ID";
9
9
  readonly posthogProjectApiKey: "NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY";
10
- readonly posthogSessionReplayEnabled: "NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED";
11
- readonly posthogSessionReplaySampleRate: "NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE";
12
10
  readonly supportEmail: "NEXT_PUBLIC_FUNNEL_SUPPORT_EMAIL";
13
11
  readonly iosAppStoreUrl: "NEXT_PUBLIC_IOS_APP_STORE_URL";
14
12
  readonly androidPlayStoreUrl: "NEXT_PUBLIC_ANDROID_PLAY_STORE_URL";
@@ -36,8 +34,6 @@ export type RuntimePublicConfig = {
36
34
  funnelVersionId: string;
37
35
  projectId: string;
38
36
  posthogProjectApiKey: string;
39
- posthogSessionReplayEnabled: boolean;
40
- posthogSessionReplaySampleRate: number;
41
37
  supportEmail: string;
42
38
  iosAppStoreUrl: string | null;
43
39
  androidPlayStoreUrl: string | null;
@@ -1,4 +1,3 @@
1
- var _a, _b;
2
1
  import { RUNTIME_ENV_KEYS, isDevelopmentRuntime, readRuntimeEnv, runtimeEnvConfig, } from '../config/env.config.js';
3
2
  import { PROJECT_ENV_STANDARD_KEYS } from './project-env.js';
4
3
  export { isDevelopmentRuntime, readRuntimeEnv };
@@ -31,8 +30,6 @@ export const RUNTIME_PUBLIC_ENV_KEYS = {
31
30
  funnelVersionId: RUNTIME_ENV_KEYS.funnelVersionId,
32
31
  projectId: RUNTIME_ENV_KEYS.projectId,
33
32
  posthogProjectApiKey: RUNTIME_ENV_KEYS.posthogProjectApiKey,
34
- posthogSessionReplayEnabled: RUNTIME_ENV_KEYS.posthogSessionReplayEnabled,
35
- posthogSessionReplaySampleRate: RUNTIME_ENV_KEYS.posthogSessionReplaySampleRate,
36
33
  supportEmail: RUNTIME_ENV_KEYS.supportEmail,
37
34
  iosAppStoreUrl: RUNTIME_ENV_KEYS.iosAppStoreUrl,
38
35
  androidPlayStoreUrl: RUNTIME_ENV_KEYS.androidPlayStoreUrl,
@@ -62,8 +59,6 @@ export const runtimePublicConfig = Object.freeze({
62
59
  funnelVersionId: readRequiredRuntimeValue(runtimeEnvConfig.funnelVersionId, ''),
63
60
  projectId: readRequiredRuntimeValue(runtimeEnvConfig.projectId, ''),
64
61
  posthogProjectApiKey: readRequiredRuntimeValue(runtimeEnvConfig.posthogProjectApiKey, ''),
65
- posthogSessionReplayEnabled: ((_a = runtimeEnvConfig.posthogSessionReplayEnabled) === null || _a === void 0 ? void 0 : _a.trim()) === 'true',
66
- posthogSessionReplaySampleRate: Math.min(100, Math.max(1, Number.parseInt(((_b = runtimeEnvConfig.posthogSessionReplaySampleRate) === null || _b === void 0 ? void 0 : _b.trim()) || '10', 10) || 10)),
67
62
  supportEmail: readRequiredRuntimeValue(runtimeEnvConfig.supportEmail, DEFAULT_SUPPORT_EMAIL),
68
63
  iosAppStoreUrl: toOptionalEnv(runtimeEnvConfig.iosAppStoreUrl) || toIosAppStoreUrlFromId(appStoreId),
69
64
  androidPlayStoreUrl: toOptionalEnv(runtimeEnvConfig.androidPlayStoreUrl) ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/runtime",
3
- "version": "0.7.14",
3
+ "version": "0.7.16",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/The-Solid-Grove/funnelsgrove.git",