@funnelsgrove/runtime 0.2.0 → 0.4.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.
@@ -55,6 +55,7 @@ export type GeneratedOfferSetDiscount = {
55
55
  readonly metadata?: Record<string, unknown> | null;
56
56
  };
57
57
  export type GeneratedOfferSet = {
58
+ readonly id?: string | null;
58
59
  readonly key: string;
59
60
  readonly isActive?: boolean | null;
60
61
  readonly metadata?: Record<string, unknown> | null;
@@ -74,6 +75,7 @@ export type OfferSetRuntimeDiscount = {
74
75
  readonly previousDiscountPercent: number;
75
76
  };
76
77
  export type OfferSetRuntimePlanOverrides = {
78
+ offerSetId?: string;
77
79
  offerSetKey?: string;
78
80
  projectPlanId?: string;
79
81
  providerPlanId?: string;
@@ -159,7 +159,7 @@ const buildGeneratedPlanOverrides = (item, mode, isDefault) => {
159
159
  return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (projectPlanId ? { projectPlanId } : {})), (providerPlanId ? { providerPlanId } : {})), (paymentMode ? { paymentMode } : {})), (analyticsPurchaseValue !== null ? { analyticsPurchaseValue } : {})), (title ? { title } : {})), (description ? { description } : {})), (priceLabel ? { priceLabel } : {})), (perDayAmount ? { perDayAmount } : {})), (perDayLabel ? { perDayLabel } : {})), (amountCents !== null ? { amountCents: Math.max(0, Math.round(amountCents)) } : {})), (checkoutSummaryLabel ? { checkoutSummaryLabel } : {})), (billingInterval ? { billingInterval } : {})), (billingIntervalCount !== null ? { billingIntervalCount: Math.max(1, Math.round(billingIntervalCount)) } : {})), (followUpProviderPlanId ? { followUpProviderPlanId } : {})), (followUpPlanTitle ? { followUpPlanTitle } : {})), (followUpBillingInterval ? { followUpBillingInterval } : {})), (followUpBillingIntervalCount !== null ? { followUpBillingIntervalCount: Math.max(1, Math.round(followUpBillingIntervalCount)) } : {})), (introIterations !== null ? { introIterations: Math.max(1, Math.round(introIterations)) } : {})), (featuredTag ? { featuredTag } : {})), (oldPriceLabel ? { oldPriceLabel } : {})), (isDefault ? { isDefault: true } : {}));
160
160
  };
161
161
  export const applyGeneratedOfferSetToPlanCatalog = (baseCatalog, mode, offerSet) => {
162
- var _a, _b, _c;
162
+ var _a, _b, _c, _d;
163
163
  if (!offerSet) {
164
164
  return Object.assign({}, baseCatalog);
165
165
  }
@@ -179,7 +179,7 @@ export const applyGeneratedOfferSetToPlanCatalog = (baseCatalog, mode, offerSet)
179
179
  if (!key) {
180
180
  continue;
181
181
  }
182
- nextCatalog[key] = Object.assign(Object.assign(Object.assign({}, ((_c = nextCatalog[key]) !== null && _c !== void 0 ? _c : {})), { offerSetKey: offerSet.key }), buildGeneratedPlanOverrides(item, mode, getOfferSetItemKind(item) === 'plan' && key === defaultPlanKey));
182
+ nextCatalog[key] = Object.assign(Object.assign(Object.assign(Object.assign({}, ((_c = nextCatalog[key]) !== null && _c !== void 0 ? _c : {})), (((_d = offerSet.id) === null || _d === void 0 ? void 0 : _d.trim()) ? { offerSetId: offerSet.id.trim() } : {})), { offerSetKey: offerSet.key }), buildGeneratedPlanOverrides(item, mode, getOfferSetItemKind(item) === 'plan' && key === defaultPlanKey));
183
183
  }
184
184
  return nextCatalog;
185
185
  };
@@ -324,8 +324,7 @@ export function useFunnelFlowController({ api = apiService, analytics, stepContr
324
324
  const attributesRef = useRef(attributes);
325
325
  const postHogFeatureFlagsRef = useRef({});
326
326
  const prevStepIdRef = useRef(null);
327
- const funnelStartedTrackedRef = useRef(false);
328
- const firstStepViewedVisitRef = useRef(null);
327
+ const firstStepViewedTrackedRef = useRef(false);
329
328
  const firstStepClickedVisitRef = useRef(null);
330
329
  // One controller mount is one funnel run. A full reload intentionally begins a new run.
331
330
  const funnelCompletionClaimedRef = useRef(false);
@@ -968,7 +967,7 @@ export function useFunnelFlowController({ api = apiService, analytics, stepContr
968
967
  safeActiveStepId,
969
968
  ]);
970
969
  useEffect(() => {
971
- var _a, _b, _c;
970
+ var _a, _b;
972
971
  if (safeActiveStepId !== activeStepId) {
973
972
  logger.warn(`[FunnelFlow] Unknown or non-renderable step "${activeStepId}", falling back to "${safeActiveStepId}".`);
974
973
  claimCurrentVisit({ type: 'exit', reason: 'replace' });
@@ -1021,10 +1020,10 @@ export function useFunnelFlowController({ api = apiService, analytics, stepContr
1021
1020
  featureFlags: postHogFeatureFlagsRef.current,
1022
1021
  });
1023
1022
  if (safeActiveStepId === defaultStepId) {
1024
- const initialAttribution = takeInitialFunnelAttributionMetadata(funnelStartedTrackedRef.current, attributionReady, initialAttributionRef.current);
1025
- funnelStartedTrackedRef.current = initialAttribution.tracked;
1023
+ const initialAttribution = takeInitialFunnelAttributionMetadata(firstStepViewedTrackedRef.current, attributionReady, initialAttributionRef.current);
1024
+ firstStepViewedTrackedRef.current = initialAttribution.tracked;
1026
1025
  if (initialAttribution.metadata) {
1027
- (_b = analytics === null || analytics === void 0 ? void 0 : analytics.trackFunnelStarted) === null || _b === void 0 ? void 0 : _b.call(analytics, {
1026
+ (_b = analytics === null || analytics === void 0 ? void 0 : analytics.trackFirstStepViewed) === null || _b === void 0 ? void 0 : _b.call(analytics, {
1028
1027
  userId: currentUserIdRef.current,
1029
1028
  environment: analyticsRuntimeMode,
1030
1029
  stepId: renderedStepId,
@@ -1036,20 +1035,6 @@ export function useFunnelFlowController({ api = apiService, analytics, stepContr
1036
1035
  featureFlags: postHogFeatureFlagsRef.current,
1037
1036
  });
1038
1037
  }
1039
- if (firstStepViewedVisitRef.current !== startIntent.visit.visitId) {
1040
- firstStepViewedVisitRef.current = startIntent.visit.visitId;
1041
- (_c = analytics === null || analytics === void 0 ? void 0 : analytics.trackFirstStepViewed) === null || _c === void 0 ? void 0 : _c.call(analytics, {
1042
- userId: currentUserIdRef.current,
1043
- environment: analyticsRuntimeMode,
1044
- stepId: renderedStepId,
1045
- stepName,
1046
- stepType,
1047
- stepContractVersion,
1048
- occurredAt: startedAt,
1049
- metadata: attributionMetadata,
1050
- featureFlags: postHogFeatureFlagsRef.current,
1051
- });
1052
- }
1053
1038
  }
1054
1039
  }
1055
1040
  }, [
@@ -10,6 +10,8 @@ export type FunnelSdkJsonObject = Record<string, unknown>;
10
10
  export type FunnelSdkListPaymentPlansResponse = {
11
11
  funnelId?: string;
12
12
  environment?: FunnelSdkRuntimeMode;
13
+ offerSetId?: string;
14
+ offerSetKey?: string;
13
15
  plans: FunnelSdkPaymentPlan[];
14
16
  };
15
17
  export type FunnelSdkBootstrapUserInput = {
@@ -72,6 +74,7 @@ export type FunnelSdkUploadPhotoInput = {
72
74
  };
73
75
  export type FunnelSdkCreateHostedCheckoutSessionInput = {
74
76
  planId: string;
77
+ offerSetId?: string | null;
75
78
  offerSetKey?: string | null;
76
79
  amountCents: number;
77
80
  successUrl: string;
@@ -95,6 +98,7 @@ export type FunnelSdkCreateHostedCheckoutSessionResponse = {
95
98
  };
96
99
  export type FunnelSdkCreateSubscriptionCheckoutInput = {
97
100
  planId: string;
101
+ offerSetId?: string | null;
98
102
  offerSetKey?: string | null;
99
103
  amountCents: number;
100
104
  returnUrl: string;
@@ -124,6 +128,7 @@ export type FunnelSdkCreateSubscriptionCheckoutResponse = {
124
128
  };
125
129
  export type FunnelSdkCreateOneTimeCheckoutInput = {
126
130
  planId: string;
131
+ offerSetId?: string | null;
127
132
  offerSetKey?: string | null;
128
133
  amountCents: number;
129
134
  returnUrl: string;
@@ -146,6 +151,7 @@ export type FunnelSdkCreateOneTimeCheckoutResponse = {
146
151
  export type FunnelSdkUpdateSubscriptionCheckoutPlanInput = {
147
152
  checkoutSessionId: string;
148
153
  planId: string;
154
+ offerSetId?: string | null;
149
155
  offerSetKey?: string | null;
150
156
  amountCents: number;
151
157
  analyticsMetadata?: Record<string, unknown> | null;
@@ -187,6 +193,8 @@ export type FunnelSdkVerifySubscriptionCheckoutResponse = {
187
193
  */
188
194
  export type FunnelSdkCreateOneTimePaymentIntentInput = {
189
195
  planId: string;
196
+ offerSetId?: string | null;
197
+ offerSetKey?: string | null;
190
198
  amountCents: number;
191
199
  analyticsMetadata?: Record<string, unknown> | null;
192
200
  couponId?: string | null;
@@ -250,6 +258,8 @@ declare class FunnelSdkService {
250
258
  uploadPhoto<ResponsePayload = FunnelSdkJsonObject>(input: FunnelSdkUploadPhotoInput): Promise<ResponsePayload>;
251
259
  listPaymentPlans(input?: {
252
260
  environment?: FunnelSdkRuntimeMode;
261
+ offerSetId?: string | null;
262
+ offerSetKey?: string | null;
253
263
  runtimeConfig?: FunnelSdkRuntimeConfigOverrides;
254
264
  }): Promise<FunnelSdkListPaymentPlansResponse>;
255
265
  createHostedCheckoutSession(input: FunnelSdkCreateHostedCheckoutSessionInput): Promise<FunnelSdkCreateHostedCheckoutSessionResponse>;
@@ -193,6 +193,8 @@ class FunnelSdkService {
193
193
  searchParams: {
194
194
  environment: input.environment,
195
195
  funnelId,
196
+ offerSetId: input.offerSetId,
197
+ offerSetKey: input.offerSetKey,
196
198
  },
197
199
  errorMessage: 'Unable to load payment plans',
198
200
  });
@@ -201,6 +203,7 @@ class FunnelSdkService {
201
203
  return this.postJson('/sdk/public/payments/checkout-session', {
202
204
  runtimeConfig: input.runtimeConfig,
203
205
  body: {
206
+ offerSetId: input.offerSetId,
204
207
  offerSetKey: input.offerSetKey,
205
208
  planId: input.planId,
206
209
  providerPlanId: input.providerPlanId,
@@ -224,6 +227,7 @@ class FunnelSdkService {
224
227
  return this.postJson('/sdk/public/payments/subscriptions', {
225
228
  runtimeConfig: input.runtimeConfig,
226
229
  body: {
230
+ offerSetId: input.offerSetId,
227
231
  offerSetKey: input.offerSetKey,
228
232
  planId: input.planId,
229
233
  providerPlanId: input.providerPlanId,
@@ -251,6 +255,7 @@ class FunnelSdkService {
251
255
  return this.postJson('/sdk/public/payments/one-time-checkout', {
252
256
  runtimeConfig: input.runtimeConfig,
253
257
  body: {
258
+ offerSetId: input.offerSetId,
254
259
  offerSetKey: input.offerSetKey,
255
260
  planId: input.planId,
256
261
  providerPlanId: input.providerPlanId,
@@ -272,6 +277,7 @@ class FunnelSdkService {
272
277
  runtimeConfig: input.runtimeConfig,
273
278
  body: {
274
279
  checkoutSessionId: input.checkoutSessionId,
280
+ offerSetId: input.offerSetId,
275
281
  offerSetKey: input.offerSetKey,
276
282
  planId: input.planId,
277
283
  providerPlanId: input.providerPlanId,
@@ -306,6 +312,8 @@ class FunnelSdkService {
306
312
  return this.postJson('/sdk/public/payments/intents', {
307
313
  runtimeConfig: input.runtimeConfig,
308
314
  body: {
315
+ offerSetId: input.offerSetId,
316
+ offerSetKey: input.offerSetKey,
309
317
  planId: input.planId,
310
318
  amountCents: input.amountCents,
311
319
  couponId: input.couponId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/runtime",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/The-Solid-Grove/funnelsgrove.git",