@funnelsgrove/runtime 0.11.2 → 0.11.3

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.
Files changed (123) hide show
  1. package/README.md +51 -0
  2. package/dist/components/ManageSubscriptionScreen.js +7 -2
  3. package/dist/services/api.service.d.ts +28 -104
  4. package/dist/services/api.service.js +24 -519
  5. package/dist/services/funnel-sdk/checkout/chargeOneClickPayment.d.ts +2 -0
  6. package/dist/services/funnel-sdk/checkout/chargeOneClickPayment.js +17 -0
  7. package/dist/services/funnel-sdk/checkout/createHostedCheckoutSession.d.ts +2 -0
  8. package/dist/services/funnel-sdk/checkout/createHostedCheckoutSession.js +9 -0
  9. package/dist/services/funnel-sdk/checkout/createOneTimeCheckout.d.ts +2 -0
  10. package/dist/services/funnel-sdk/checkout/createOneTimeCheckout.js +18 -0
  11. package/dist/services/funnel-sdk/checkout/createOneTimePaymentIntent.d.ts +3 -0
  12. package/dist/services/funnel-sdk/checkout/createOneTimePaymentIntent.js +10 -0
  13. package/dist/services/funnel-sdk/checkout/createSubscriptionCheckout.d.ts +2 -0
  14. package/dist/services/funnel-sdk/checkout/createSubscriptionCheckout.js +19 -0
  15. package/dist/services/funnel-sdk/checkout/requests.d.ts +126 -0
  16. package/dist/services/funnel-sdk/checkout/requests.js +111 -0
  17. package/dist/services/funnel-sdk/checkout/types.d.ts +183 -0
  18. package/dist/services/funnel-sdk/checkout/types.js +1 -0
  19. package/dist/services/funnel-sdk/checkout/updateSubscriptionCheckoutPlan.d.ts +2 -0
  20. package/dist/services/funnel-sdk/checkout/updateSubscriptionCheckoutPlan.js +18 -0
  21. package/dist/services/funnel-sdk/checkout/verifySubscriptionCheckout.d.ts +2 -0
  22. package/dist/services/funnel-sdk/checkout/verifySubscriptionCheckout.js +18 -0
  23. package/dist/services/funnel-sdk/shared/http.d.ts +20 -0
  24. package/dist/services/funnel-sdk/shared/http.js +65 -0
  25. package/dist/services/funnel-sdk/shared/runtimeConfig.d.ts +17 -0
  26. package/dist/services/funnel-sdk/shared/runtimeConfig.js +42 -0
  27. package/dist/services/funnel-sdk/shared/types.d.ts +9 -0
  28. package/dist/services/funnel-sdk/shared/types.js +1 -0
  29. package/dist/services/funnel-sdk/subscriptions/listSubscriptions.d.ts +3 -0
  30. package/dist/services/funnel-sdk/subscriptions/listSubscriptions.js +17 -0
  31. package/dist/services/funnel-sdk/subscriptions/types.d.ts +24 -0
  32. package/dist/services/funnel-sdk/subscriptions/types.js +1 -0
  33. package/dist/services/funnel-sdk/subscriptions/updateSubscription.d.ts +2 -0
  34. package/dist/services/funnel-sdk/subscriptions/updateSubscription.js +33 -0
  35. package/dist/services/funnel-sdk/subscriptions/validator.d.ts +2 -0
  36. package/dist/services/funnel-sdk/subscriptions/validator.js +15 -0
  37. package/dist/services/funnel-sdk/uploads/preparePhotoUpload.d.ts +4 -0
  38. package/dist/services/funnel-sdk/uploads/preparePhotoUpload.js +19 -0
  39. package/dist/services/funnel-sdk/uploads/types.d.ts +32 -0
  40. package/dist/services/funnel-sdk/uploads/types.js +1 -0
  41. package/dist/services/funnel-sdk/uploads/uploadPhoto.d.ts +7 -0
  42. package/dist/services/funnel-sdk/uploads/uploadPhoto.js +18 -0
  43. package/dist/services/funnel-sdk/uploads/uploadPhotoFile.d.ts +2 -0
  44. package/dist/services/funnel-sdk/uploads/uploadPhotoFile.js +26 -0
  45. package/dist/services/funnel-sdk/users/bootstrapUser.d.ts +3 -0
  46. package/dist/services/funnel-sdk/users/bootstrapUser.js +15 -0
  47. package/dist/services/funnel-sdk/users/captureEmail.d.ts +2 -0
  48. package/dist/services/funnel-sdk/users/captureEmail.js +15 -0
  49. package/dist/services/funnel-sdk/users/claimUserSubscription.d.ts +3 -0
  50. package/dist/services/funnel-sdk/users/claimUserSubscription.js +7 -0
  51. package/dist/services/funnel-sdk/users/getCurrentUser.d.ts +3 -0
  52. package/dist/services/funnel-sdk/users/getCurrentUser.js +13 -0
  53. package/dist/services/funnel-sdk/users/getUserSubscriptionStatus.d.ts +3 -0
  54. package/dist/services/funnel-sdk/users/getUserSubscriptionStatus.js +14 -0
  55. package/dist/services/funnel-sdk/users/types.d.ts +57 -0
  56. package/dist/services/funnel-sdk/users/types.js +1 -0
  57. package/dist/services/funnel-sdk/users/updateFunnelUser.d.ts +3 -0
  58. package/dist/services/funnel-sdk/users/updateFunnelUser.js +18 -0
  59. package/dist/services/funnel-sdk.service.d.ts +26 -319
  60. package/dist/services/funnel-sdk.service.js +38 -456
  61. package/dist/services/session/bootstrap/bootstrapSession.d.ts +8 -0
  62. package/dist/services/session/bootstrap/bootstrapSession.js +23 -0
  63. package/dist/services/session/bootstrap/currentUser.d.ts +1 -0
  64. package/dist/services/session/bootstrap/currentUser.js +37 -0
  65. package/dist/services/session/bootstrap/idempotency.d.ts +9 -0
  66. package/dist/services/session/bootstrap/idempotency.js +97 -0
  67. package/dist/services/session/bootstrap/requests.d.ts +23 -0
  68. package/dist/services/session/bootstrap/requests.js +25 -0
  69. package/dist/services/session/bootstrap/responses.d.ts +3 -0
  70. package/dist/services/session/bootstrap/responses.js +10 -0
  71. package/dist/services/session/bootstrap/types.d.ts +11 -0
  72. package/dist/services/session/bootstrap/types.js +1 -0
  73. package/dist/services/session/emailCapture/captureEmail.d.ts +8 -0
  74. package/dist/services/session/emailCapture/captureEmail.js +13 -0
  75. package/dist/services/session/emailCapture/requests.d.ts +12 -0
  76. package/dist/services/session/emailCapture/requests.js +6 -0
  77. package/dist/services/session/emailCapture/responses.d.ts +3 -0
  78. package/dist/services/session/emailCapture/responses.js +14 -0
  79. package/dist/services/session/emailCapture/types.d.ts +8 -0
  80. package/dist/services/session/emailCapture/types.js +1 -0
  81. package/dist/services/session/emailCapture/validator.d.ts +16 -0
  82. package/dist/services/session/emailCapture/validator.js +37 -0
  83. package/dist/services/session/identity.d.ts +6 -0
  84. package/dist/services/session/identity.js +48 -0
  85. package/dist/services/session/ping/pingUserContext.d.ts +2 -0
  86. package/dist/services/session/ping/pingUserContext.js +10 -0
  87. package/dist/services/session/ping/transport.d.ts +2 -0
  88. package/dist/services/session/ping/transport.js +41 -0
  89. package/dist/services/session/shared/values.d.ts +6 -0
  90. package/dist/services/session/shared/values.js +25 -0
  91. package/dist/services/session/subscriptions/getManageSubscriptions.d.ts +3 -0
  92. package/dist/services/session/subscriptions/getManageSubscriptions.js +8 -0
  93. package/dist/services/session/subscriptions/identity.d.ts +3 -0
  94. package/dist/services/session/subscriptions/identity.js +8 -0
  95. package/dist/services/session/subscriptions/types.d.ts +35 -0
  96. package/dist/services/session/subscriptions/types.js +1 -0
  97. package/dist/services/session/subscriptions/updateSubscription.d.ts +10 -0
  98. package/dist/services/session/subscriptions/updateSubscription.js +7 -0
  99. package/dist/services/session/subscriptions/validator.d.ts +6 -0
  100. package/dist/services/session/subscriptions/validator.js +13 -0
  101. package/dist/services/session/uploads/localPhoto.d.ts +2 -0
  102. package/dist/services/session/uploads/localPhoto.js +10 -0
  103. package/dist/services/session/uploads/requests.d.ts +10 -0
  104. package/dist/services/session/uploads/requests.js +7 -0
  105. package/dist/services/session/uploads/types.d.ts +7 -0
  106. package/dist/services/session/uploads/types.js +1 -0
  107. package/dist/services/session/uploads/uploadTempPhoto.d.ts +6 -0
  108. package/dist/services/session/uploads/uploadTempPhoto.js +13 -0
  109. package/dist/services/session/uploads/validator.d.ts +3 -0
  110. package/dist/services/session/uploads/validator.js +12 -0
  111. package/dist/services/session/users/mappers.d.ts +13 -0
  112. package/dist/services/session/users/mappers.js +33 -0
  113. package/dist/services/session/users/requests.d.ts +15 -0
  114. package/dist/services/session/users/requests.js +8 -0
  115. package/dist/services/session/users/syncUrlUserAttributes.d.ts +10 -0
  116. package/dist/services/session/users/syncUrlUserAttributes.js +21 -0
  117. package/dist/services/session/users/types.d.ts +20 -0
  118. package/dist/services/session/users/types.js +1 -0
  119. package/dist/services/session/users/updateUser.d.ts +6 -0
  120. package/dist/services/session/users/updateUser.js +18 -0
  121. package/package.json +1 -1
  122. /package/dist/services/{funnel-sdk-payments.functions.d.ts → funnel-sdk/checkout/selection.d.ts} +0 -0
  123. /package/dist/services/{funnel-sdk-payments.functions.js → funnel-sdk/checkout/selection.js} +0 -0
@@ -0,0 +1,23 @@
1
+ import type { BootstrapProfile } from './types.js';
2
+ export declare const toBootstrapProfile: (input?: BootstrapProfile) => BootstrapProfile;
3
+ export declare const toBootstrapRequest: (userId: string, profile: BootstrapProfile, environment: "test" | "live") => {
4
+ userId: string;
5
+ email: string | undefined;
6
+ fullName: string | undefined;
7
+ metadata: {
8
+ source: string;
9
+ environment: "test" | "live";
10
+ };
11
+ attribution: import("../../../index.js").FunnelUserAttribution | undefined;
12
+ };
13
+ export declare const toBootstrapFingerprint: (request: ReturnType<typeof toBootstrapRequest>, funnelVersionId: string) => {
14
+ funnelVersionId: string | null;
15
+ userId: string;
16
+ email: string | null;
17
+ fullName: string | null;
18
+ metadata: {
19
+ source: string;
20
+ environment: "test" | "live";
21
+ };
22
+ attribution: import("../../../index.js").FunnelUserAttribution;
23
+ };
@@ -0,0 +1,25 @@
1
+ import { mergeFunnelUserAttribution } from '../../../runtime/funnel-attribution.js';
2
+ import { asString } from '../shared/values.js';
3
+ export const toBootstrapProfile = (input) => ({
4
+ email: (input === null || input === void 0 ? void 0 : input.email) || undefined,
5
+ name: (input === null || input === void 0 ? void 0 : input.name) || undefined,
6
+ attribution: input === null || input === void 0 ? void 0 : input.attribution,
7
+ });
8
+ export const toBootstrapRequest = (userId, profile, environment) => ({
9
+ userId,
10
+ email: profile.email,
11
+ fullName: profile.name,
12
+ metadata: { source: 'funnel-session', environment },
13
+ attribution: profile.attribution,
14
+ });
15
+ export const toBootstrapFingerprint = (request, funnelVersionId) => {
16
+ var _a, _b;
17
+ return ({
18
+ funnelVersionId: asString(funnelVersionId),
19
+ userId: request.userId,
20
+ email: (_b = (_a = asString(request.email)) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : null,
21
+ fullName: asString(request.fullName),
22
+ metadata: request.metadata,
23
+ attribution: mergeFunnelUserAttribution({}, request.attribution),
24
+ });
25
+ };
@@ -0,0 +1,3 @@
1
+ import type { BootstrapProfile, SessionBootstrapResponse } from './types.js';
2
+ export declare const resolveBootstrapResponseUserId: (payload: SessionBootstrapResponse, fallbackUserId: string) => string;
3
+ export declare const toBootstrapUser: (userId: string, profile: BootstrapProfile, payload?: SessionBootstrapResponse) => import("../users/types.js").AppUser;
@@ -0,0 +1,10 @@
1
+ import { asString } from '../shared/values.js';
2
+ import { toAppUser, withMergedAttributionDocument } from '../users/mappers.js';
3
+ export const resolveBootstrapResponseUserId = (payload, fallbackUserId) => { var _a; return asString((_a = payload.user) === null || _a === void 0 ? void 0 : _a.user_id) || asString(payload.user_id) || fallbackUserId; };
4
+ export const toBootstrapUser = (userId, profile, payload) => toAppUser({
5
+ apiUser: payload === null || payload === void 0 ? void 0 : payload.user,
6
+ userId,
7
+ fallbackName: profile.name,
8
+ fallbackEmail: profile.email,
9
+ fallbackDocument: withMergedAttributionDocument({}, profile.attribution),
10
+ });
@@ -0,0 +1,11 @@
1
+ import type { FunnelUserAttribution } from '../../../runtime/funnel-attribution.js';
2
+ import type { SdkApiUser } from '../users/types.js';
3
+ export type BootstrapProfile = {
4
+ email?: string;
5
+ name?: string;
6
+ attribution?: FunnelUserAttribution;
7
+ };
8
+ export type SessionBootstrapResponse = {
9
+ user?: SdkApiUser;
10
+ user_id?: unknown;
11
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { FunnelUserAnswers } from '../../../sdk/userAnswers.js';
2
+ import type { EmailCaptureResult } from './types.js';
3
+ export declare function captureEmail(input: {
4
+ userId: string;
5
+ email: string;
6
+ environment: 'test' | 'live';
7
+ answers?: FunnelUserAnswers;
8
+ }): Promise<EmailCaptureResult>;
@@ -0,0 +1,13 @@
1
+ import { FUNNEL_ID } from '../../runtime-api.config.js';
2
+ import { funnelSdkService } from '../../funnel-sdk.service.js';
3
+ import { persistUserId } from '../identity.js';
4
+ import { toEmailCaptureRequest } from './requests.js';
5
+ import { parseEmailCaptureResponse } from './validator.js';
6
+ import { toEmailCaptureResult } from './responses.js';
7
+ export async function captureEmail(input) {
8
+ const request = toEmailCaptureRequest(input);
9
+ const payload = await funnelSdkService.captureEmail(request);
10
+ const response = parseEmailCaptureResponse(payload, request);
11
+ const userId = persistUserId(request.userId, FUNNEL_ID);
12
+ return toEmailCaptureResult(response, userId, request.email);
13
+ }
@@ -0,0 +1,12 @@
1
+ import type { FunnelUserAnswers } from '../../../sdk/userAnswers.js';
2
+ export declare const toEmailCaptureRequest: (input: {
3
+ userId: string;
4
+ email: string;
5
+ environment: "test" | "live";
6
+ answers?: FunnelUserAnswers;
7
+ }) => {
8
+ userId: string;
9
+ email: string;
10
+ environment: "test" | "live";
11
+ answers: FunnelUserAnswers | undefined;
12
+ };
@@ -0,0 +1,6 @@
1
+ export const toEmailCaptureRequest = (input) => ({
2
+ userId: input.userId.trim(),
3
+ email: input.email.trim().toLowerCase(),
4
+ environment: input.environment,
5
+ answers: input.answers,
6
+ });
@@ -0,0 +1,3 @@
1
+ import type { EmailCaptureResult } from './types.js';
2
+ import type { parseEmailCaptureResponse } from './validator.js';
3
+ export declare const toEmailCaptureResult: (response: ReturnType<typeof parseEmailCaptureResponse>, userId: string, email: string) => EmailCaptureResult;
@@ -0,0 +1,14 @@
1
+ import { toAppUser } from '../users/mappers.js';
2
+ export const toEmailCaptureResult = (response, userId, email) => ({
3
+ user: toAppUser({
4
+ apiUser: Object.assign(Object.assign({}, response.user), { user_id: userId, email }),
5
+ userId,
6
+ fallbackEmail: email,
7
+ }),
8
+ eventId: response.eventId,
9
+ eventCreated: response.eventCreated,
10
+ canonicalUser: response.canonicalUserId
11
+ ? { id: response.canonicalUserId, name: '', email, attributes: {}, document: {} }
12
+ : null,
13
+ activeSubscription: response.activeSubscription,
14
+ });
@@ -0,0 +1,8 @@
1
+ import type { AppUser } from '../users/types.js';
2
+ export type EmailCaptureResult = {
3
+ user: AppUser;
4
+ eventId: string;
5
+ eventCreated: boolean;
6
+ canonicalUser: AppUser | null;
7
+ activeSubscription: boolean;
8
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { FunnelSdkCaptureEmailResponse } from '../../funnel-sdk.service.js';
2
+ export declare const parseEmailCaptureResponse: (payload: FunnelSdkCaptureEmailResponse, expected: {
3
+ userId: string;
4
+ email: string;
5
+ }) => {
6
+ user: {
7
+ user_id?: unknown;
8
+ fullName?: unknown;
9
+ email?: unknown;
10
+ document?: unknown;
11
+ };
12
+ canonicalUserId: string | null;
13
+ eventId: string;
14
+ eventCreated: boolean;
15
+ activeSubscription: boolean;
16
+ };
@@ -0,0 +1,37 @@
1
+ import { asString, isRecord } from '../shared/values.js';
2
+ export const parseEmailCaptureResponse = (payload, expected) => {
3
+ var _a, _b, _c, _d;
4
+ const { userId, email } = expected;
5
+ const eventId = asString(payload.eventId);
6
+ const responseUser = isRecord(payload.user) ? payload.user : null;
7
+ const responseUserId = responseUser === null || responseUser === void 0 ? void 0 : responseUser.user_id;
8
+ const responseEmail = (_b = (_a = asString(responseUser === null || responseUser === void 0 ? void 0 : responseUser.email)) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : null;
9
+ const canonicalUserValue = payload.canonicalUser;
10
+ const canonicalUserRecord = isRecord(canonicalUserValue) ? canonicalUserValue : null;
11
+ const canonicalUserId = asString(canonicalUserRecord === null || canonicalUserRecord === void 0 ? void 0 : canonicalUserRecord.user_id);
12
+ const canonicalUserEmail = (_d = (_c = asString(canonicalUserRecord === null || canonicalUserRecord === void 0 ? void 0 : canonicalUserRecord.email)) === null || _c === void 0 ? void 0 : _c.toLowerCase()) !== null && _d !== void 0 ? _d : null;
13
+ const hasCanonicalUser = canonicalUserValue !== undefined && canonicalUserValue !== null;
14
+ const canonicalUserKeys = canonicalUserRecord ? Object.keys(canonicalUserRecord) : [];
15
+ if (!eventId
16
+ || typeof payload.eventCreated !== 'boolean'
17
+ || typeof payload.activeSubscription !== 'boolean'
18
+ || !responseUser
19
+ || typeof responseUserId !== 'string'
20
+ || responseUserId !== userId
21
+ || responseEmail !== email
22
+ || (hasCanonicalUser
23
+ && (!canonicalUserRecord
24
+ || !canonicalUserId
25
+ || canonicalUserEmail !== email
26
+ || canonicalUserKeys.length !== 2
27
+ || canonicalUserKeys.some((key) => key !== 'user_id' && key !== 'email')))) {
28
+ throw new Error('Invalid email capture response');
29
+ }
30
+ return {
31
+ user: responseUser,
32
+ canonicalUserId,
33
+ eventId,
34
+ eventCreated: payload.eventCreated,
35
+ activeSubscription: payload.activeSubscription,
36
+ };
37
+ };
@@ -0,0 +1,6 @@
1
+ export declare const generateUserId: () => string;
2
+ export declare const readStoredUserId: (funnelId?: string | null | undefined) => string | null;
3
+ export declare const persistUserId: (value: string, funnelId?: string | null | undefined) => string;
4
+ export declare function getOrCreateClientUserId(): string;
5
+ export declare function persistCanonicalUserId(userId: string): string;
6
+ export declare function getBootstrapCandidateUserId(fallbackUserId?: string | null): string | null;
@@ -0,0 +1,48 @@
1
+ import { FUNNEL_ID } from '../runtime-api.config.js';
2
+ import { resolveUrlUserAttributes } from '../../runtime/url-user-attributes.js';
3
+ import { asString, canUseDom, normalizeUserId } from './shared/values.js';
4
+ const DEFAULT_USER_ID_STORAGE_KEY = 'funnel:user-id';
5
+ const buildUserIdStorageKey = (funnelId = FUNNEL_ID) => {
6
+ const normalizedFunnelId = asString(funnelId);
7
+ if (!normalizedFunnelId) {
8
+ return DEFAULT_USER_ID_STORAGE_KEY;
9
+ }
10
+ return `funnel:${normalizedFunnelId}:user-id`;
11
+ };
12
+ export const generateUserId = () => {
13
+ var _a;
14
+ if (canUseDom() && typeof ((_a = window.crypto) === null || _a === void 0 ? void 0 : _a.randomUUID) === 'function') {
15
+ return `u_${window.crypto.randomUUID().replace(/-/g, '')}`;
16
+ }
17
+ return `u_${Date.now()}_${Math.random().toString(16).slice(2, 10)}`;
18
+ };
19
+ export const readStoredUserId = (funnelId = FUNNEL_ID) => {
20
+ if (!canUseDom()) {
21
+ return null;
22
+ }
23
+ return normalizeUserId(window.localStorage.getItem(buildUserIdStorageKey(funnelId)));
24
+ };
25
+ export const persistUserId = (value, funnelId = FUNNEL_ID) => {
26
+ const normalized = normalizeUserId(value) || generateUserId();
27
+ if (canUseDom()) {
28
+ window.localStorage.setItem(buildUserIdStorageKey(funnelId), normalized);
29
+ }
30
+ return normalized;
31
+ };
32
+ export function getOrCreateClientUserId() {
33
+ const existing = readStoredUserId(FUNNEL_ID);
34
+ if (existing) {
35
+ return existing;
36
+ }
37
+ return persistUserId(generateUserId(), FUNNEL_ID);
38
+ }
39
+ export function persistCanonicalUserId(userId) {
40
+ const normalizedUserId = normalizeUserId(userId);
41
+ if (!normalizedUserId) {
42
+ throw new Error('Invalid canonical user id');
43
+ }
44
+ return persistUserId(normalizedUserId, FUNNEL_ID);
45
+ }
46
+ export function getBootstrapCandidateUserId(fallbackUserId) {
47
+ return resolveUrlUserAttributes().userId || normalizeUserId(fallbackUserId);
48
+ }
@@ -0,0 +1,2 @@
1
+ import type { AppUser } from '../users/types.js';
2
+ export declare function pingUserContext(userId: string): Promise<AppUser | null>;
@@ -0,0 +1,10 @@
1
+ import { FUNNEL_ID, getFunnelSdkPublishableKey } from '../../runtime-api.config.js';
2
+ import { canUseDom, normalizeUserId } from '../shared/values.js';
3
+ import { sendUserContextPing } from './transport.js';
4
+ export async function pingUserContext(userId) {
5
+ const normalizedUserId = normalizeUserId(userId);
6
+ const publishableKey = getFunnelSdkPublishableKey();
7
+ if (!normalizedUserId || !publishableKey || !FUNNEL_ID || !canUseDom())
8
+ return null;
9
+ return sendUserContextPing(normalizedUserId);
10
+ }
@@ -0,0 +1,2 @@
1
+ import type { AppUser } from '../users/types.js';
2
+ export declare function sendUserContextPing(normalizedUserId: string): Promise<AppUser | null>;
@@ -0,0 +1,41 @@
1
+ import { FUNNEL_ID, buildSdkHeaders } from '../../runtime-api.config.js';
2
+ import { asString, canUseDom } from '../shared/values.js';
3
+ import { toAppUser } from '../users/mappers.js';
4
+ const resolveBrowserTimezone = () => {
5
+ if (!canUseDom()) {
6
+ return null;
7
+ }
8
+ try {
9
+ return asString(Intl.DateTimeFormat().resolvedOptions().timeZone);
10
+ }
11
+ catch (_a) {
12
+ return null;
13
+ }
14
+ };
15
+ export async function sendUserContextPing(normalizedUserId) {
16
+ var _a;
17
+ try {
18
+ const response = await fetch('/api/ping', {
19
+ method: 'POST',
20
+ headers: buildSdkHeaders({
21
+ 'Content-Type': 'application/json',
22
+ }),
23
+ body: JSON.stringify({
24
+ funnelId: FUNNEL_ID,
25
+ user_id: normalizedUserId,
26
+ timezone: resolveBrowserTimezone() || undefined,
27
+ }),
28
+ });
29
+ if (!response.ok) {
30
+ return null;
31
+ }
32
+ const payload = (await response.json());
33
+ return toAppUser({
34
+ apiUser: payload.user,
35
+ userId: asString((_a = payload.user) === null || _a === void 0 ? void 0 : _a.user_id) || normalizedUserId,
36
+ });
37
+ }
38
+ catch (_b) {
39
+ return null;
40
+ }
41
+ }
@@ -0,0 +1,6 @@
1
+ export declare const canUseDom: () => boolean;
2
+ export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
3
+ export declare const asRecord: (value: unknown) => Record<string, unknown>;
4
+ export declare const asString: (value: unknown) => string | null;
5
+ export declare const asNumber: (value: unknown) => number | null;
6
+ export declare const normalizeUserId: (value: string | null | undefined) => string | null;
@@ -0,0 +1,25 @@
1
+ export const canUseDom = () => {
2
+ return typeof window !== 'undefined';
3
+ };
4
+ export const isRecord = (value) => {
5
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
6
+ };
7
+ export const asRecord = (value) => {
8
+ return isRecord(value) ? value : {};
9
+ };
10
+ export const asString = (value) => {
11
+ if (typeof value !== 'string') {
12
+ return null;
13
+ }
14
+ const trimmed = value.trim();
15
+ return trimmed || null;
16
+ };
17
+ export const asNumber = (value) => {
18
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
19
+ return null;
20
+ }
21
+ return value;
22
+ };
23
+ export const normalizeUserId = (value) => {
24
+ return asString(value);
25
+ };
@@ -0,0 +1,3 @@
1
+ import type { FunnelSdkRuntimeConfigOverrides } from '../../funnel-sdk/shared/types.js';
2
+ import type { ManageSubscriptionsResponse } from './types.js';
3
+ export declare function getManageSubscriptions(runtimeConfig?: FunnelSdkRuntimeConfigOverrides): Promise<ManageSubscriptionsResponse>;
@@ -0,0 +1,8 @@
1
+ import { FUNNEL_ID } from '../../runtime-api.config.js';
2
+ import { funnelSdkService } from '../../funnel-sdk.service.js';
3
+ import { requireSubscriptionManagementIdentity, requireSubscriptionManagementUser } from './validator.js';
4
+ export async function getManageSubscriptions(runtimeConfig) {
5
+ const identity = requireSubscriptionManagementIdentity();
6
+ const payload = await funnelSdkService.listSubscriptions(Object.assign(Object.assign({}, identity), { funnelId: FUNNEL_ID || undefined, runtimeConfig }));
7
+ return requireSubscriptionManagementUser(payload);
8
+ }
@@ -0,0 +1,3 @@
1
+ export declare const SUBSCRIPTION_MANAGEMENT_LINK_ERROR = "This subscription management link is invalid or has expired. Please request a new link or contact support.";
2
+ export declare function getSubscriptionManagementUserId(): string | null;
3
+ export declare function getSubscriptionManagementStripeCustomerId(): string | null;
@@ -0,0 +1,8 @@
1
+ import { resolveUrlUserAttributes } from '../../../runtime/url-user-attributes.js';
2
+ export const SUBSCRIPTION_MANAGEMENT_LINK_ERROR = 'This subscription management link is invalid or has expired. Please request a new link or contact support.';
3
+ export function getSubscriptionManagementUserId() {
4
+ return resolveUrlUserAttributes().userId;
5
+ }
6
+ export function getSubscriptionManagementStripeCustomerId() {
7
+ return resolveUrlUserAttributes().stripeCustomerId;
8
+ }
@@ -0,0 +1,35 @@
1
+ import type { FunnelSdkSubscriptionRef } from '../../funnel-sdk/subscriptions/types.js';
2
+ export type ManageSubscriptionsResponse = {
3
+ user: {
4
+ id: string;
5
+ user_id: string;
6
+ email: string | null;
7
+ fullName: string | null;
8
+ subscriptionStatus: string | null;
9
+ } | null;
10
+ subscriptions: Array<{
11
+ id: string;
12
+ status: string;
13
+ providerSubscriptionId: string;
14
+ providerPlanId: string | null;
15
+ cancelAtPeriodEnd: boolean;
16
+ currentPeriodStart: string | null;
17
+ currentPeriodEnd: string | null;
18
+ createdAt: string | null;
19
+ amountCents?: number | null;
20
+ currency?: string | null;
21
+ billingInterval?: string | null;
22
+ billingIntervalCount?: number | null;
23
+ discountCouponIds?: string[];
24
+ retentionDiscount?: {
25
+ couponId: string;
26
+ discountPercent: number;
27
+ amountCents: number;
28
+ discountedAmountCents: number;
29
+ originalAmountCents: number;
30
+ };
31
+ environment: 'test' | 'live';
32
+ subscriptionRef?: FunnelSdkSubscriptionRef;
33
+ }>;
34
+ eventsCount: number;
35
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ import type { FunnelSdkRuntimeConfigOverrides } from '../../funnel-sdk/shared/types.js';
2
+ import type { FunnelSdkSubscriptionRef } from '../../funnel-sdk/subscriptions/types.js';
3
+ import type { ManageSubscriptionsResponse } from './types.js';
4
+ export declare function updateSubscription(input: {
5
+ subscriptionId: string;
6
+ action: 'cancel' | 'renew' | 'apply-discount';
7
+ couponId?: string | null;
8
+ subscriptionRef?: FunnelSdkSubscriptionRef;
9
+ runtimeConfig?: FunnelSdkRuntimeConfigOverrides;
10
+ }): Promise<ManageSubscriptionsResponse>;
@@ -0,0 +1,7 @@
1
+ import { FUNNEL_ID } from '../../runtime-api.config.js';
2
+ import { funnelSdkService } from '../../funnel-sdk.service.js';
3
+ import { requireSubscriptionManagementIdentity } from './validator.js';
4
+ export async function updateSubscription(input) {
5
+ const identity = requireSubscriptionManagementIdentity();
6
+ return funnelSdkService.updateSubscription(Object.assign(Object.assign({ subscriptionId: input.subscriptionId, action: input.action, couponId: input.couponId, subscriptionRef: input.subscriptionRef, runtimeConfig: input.runtimeConfig }, identity), { funnelId: FUNNEL_ID || undefined }));
7
+ }
@@ -0,0 +1,6 @@
1
+ import type { ManageSubscriptionsResponse } from './types.js';
2
+ export declare const requireSubscriptionManagementIdentity: () => {
3
+ userId: string | null;
4
+ stripeCustomerId: string | null;
5
+ };
6
+ export declare const requireSubscriptionManagementUser: (payload: ManageSubscriptionsResponse) => ManageSubscriptionsResponse;
@@ -0,0 +1,13 @@
1
+ import { SUBSCRIPTION_MANAGEMENT_LINK_ERROR, getSubscriptionManagementUserId, getSubscriptionManagementStripeCustomerId, } from './identity.js';
2
+ export const requireSubscriptionManagementIdentity = () => {
3
+ const userId = getSubscriptionManagementUserId();
4
+ const stripeCustomerId = getSubscriptionManagementStripeCustomerId();
5
+ if (!userId && !stripeCustomerId)
6
+ throw new Error(SUBSCRIPTION_MANAGEMENT_LINK_ERROR);
7
+ return { userId, stripeCustomerId };
8
+ };
9
+ export const requireSubscriptionManagementUser = (payload) => {
10
+ if (!payload.user)
11
+ throw new Error(SUBSCRIPTION_MANAGEMENT_LINK_ERROR);
12
+ return payload;
13
+ };
@@ -0,0 +1,2 @@
1
+ import type { TempPhotoUploadResult } from './types.js';
2
+ export declare const createLocalPhoto: (userId: string, file: File) => TempPhotoUploadResult;
@@ -0,0 +1,10 @@
1
+ export const createLocalPhoto = (userId, file) => {
2
+ const publicUrl = URL.createObjectURL(file);
3
+ return {
4
+ key: 'local_' + userId + '_' + Date.now(),
5
+ publicUrl,
6
+ contentType: file.type || 'image/jpeg',
7
+ sizeBytes: file.size || 0,
8
+ uploadedAt: new Date().toISOString(),
9
+ };
10
+ };
@@ -0,0 +1,10 @@
1
+ export declare const toPhotoUploadRequest: (userId: string, input: {
2
+ file: File;
3
+ source?: "camera" | "upload";
4
+ }) => {
5
+ userId: string;
6
+ fileName: string;
7
+ contentType: string | undefined;
8
+ file: File;
9
+ source: "camera" | "upload";
10
+ };
@@ -0,0 +1,7 @@
1
+ export const toPhotoUploadRequest = (userId, input) => ({
2
+ userId,
3
+ fileName: input.file.name || 'capture.jpg',
4
+ contentType: input.file.type || undefined,
5
+ file: input.file,
6
+ source: input.source || 'upload',
7
+ });
@@ -0,0 +1,7 @@
1
+ export type TempPhotoUploadResult = {
2
+ key: string;
3
+ publicUrl: string;
4
+ contentType: string;
5
+ sizeBytes: number;
6
+ uploadedAt: string;
7
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import type { TempPhotoUploadResult } from './types.js';
2
+ export declare function uploadTempPhoto(input: {
3
+ file: File;
4
+ userId?: string;
5
+ source?: 'camera' | 'upload';
6
+ }): Promise<TempPhotoUploadResult>;
@@ -0,0 +1,13 @@
1
+ import { FUNNEL_ID, getFunnelSdkPublishableKey } from '../../runtime-api.config.js';
2
+ import { funnelSdkService } from '../../funnel-sdk.service.js';
3
+ import { getOrCreateClientUserId, persistUserId } from '../identity.js';
4
+ import { toPhotoUploadRequest } from './requests.js';
5
+ import { parsePhotoUploadResponse } from './validator.js';
6
+ import { createLocalPhoto } from './localPhoto.js';
7
+ export async function uploadTempPhoto(input) {
8
+ const userId = persistUserId(input.userId || getOrCreateClientUserId(), FUNNEL_ID);
9
+ if (!getFunnelSdkPublishableKey())
10
+ return createLocalPhoto(userId, input.file);
11
+ const payload = await funnelSdkService.uploadPhotoFile(toPhotoUploadRequest(userId, input));
12
+ return parsePhotoUploadResponse(payload, input.file);
13
+ }
@@ -0,0 +1,3 @@
1
+ import type { FunnelSdkUploadedPhoto } from '../../funnel-sdk.service.js';
2
+ import type { TempPhotoUploadResult } from './types.js';
3
+ export declare const parsePhotoUploadResponse: (payload: FunnelSdkUploadedPhoto, file: File) => TempPhotoUploadResult;
@@ -0,0 +1,12 @@
1
+ import { asString, asNumber } from '../shared/values.js';
2
+ export const parsePhotoUploadResponse = (payload, file) => {
3
+ const publicUrl = asString(payload.publicUrl);
4
+ const key = asString(payload.key);
5
+ const contentType = asString(payload.contentType) || file.type || 'image/jpeg';
6
+ const sizeBytes = asNumber(payload.sizeBytes) || file.size || 0;
7
+ const uploadedAt = asString(payload.uploadedAt) || new Date().toISOString();
8
+ if (!publicUrl || !key) {
9
+ throw new Error('Invalid photo upload response');
10
+ }
11
+ return { key, publicUrl, contentType, sizeBytes, uploadedAt };
12
+ };
@@ -0,0 +1,13 @@
1
+ import type { FunnelUserAnswers } from '../../../sdk/userAnswers.js';
2
+ import { type FunnelUserAttribution } from '../../../runtime/funnel-attribution.js';
3
+ import type { AppUser, SdkApiUser } from './types.js';
4
+ export declare const withMergedAttributionDocument: (document: Record<string, unknown> | null | undefined, attribution: FunnelUserAttribution | null | undefined) => Record<string, unknown>;
5
+ export declare const toAppUser: (input: {
6
+ apiUser?: SdkApiUser;
7
+ userId: string;
8
+ fallbackName?: string;
9
+ fallbackEmail?: string;
10
+ fallbackAttributes?: FunnelUserAnswers;
11
+ fallbackDocument?: Record<string, unknown>;
12
+ }) => AppUser;
13
+ export declare const toUpdatedUser: (user: AppUser, userId: string, attribution?: FunnelUserAttribution, apiUser?: SdkApiUser) => AppUser;
@@ -0,0 +1,33 @@
1
+ import { mergeFunnelUserAttribution } from '../../../runtime/funnel-attribution.js';
2
+ import { asRecord, asString } from '../shared/values.js';
3
+ export const withMergedAttributionDocument = (document, attribution) => {
4
+ const normalizedDocument = asRecord(document);
5
+ if (!attribution) {
6
+ return normalizedDocument;
7
+ }
8
+ return Object.assign(Object.assign({}, normalizedDocument), { attribution: mergeFunnelUserAttribution(normalizedDocument.attribution, attribution) });
9
+ };
10
+ export const toAppUser = (input) => {
11
+ var _a, _b;
12
+ const apiUser = input.apiUser;
13
+ const apiDocument = asRecord(apiUser === null || apiUser === void 0 ? void 0 : apiUser.document);
14
+ const apiProgress = asRecord(apiDocument.progress);
15
+ const apiAttributes = asRecord(apiProgress.attributes);
16
+ return {
17
+ id: input.userId,
18
+ name: asString(apiUser === null || apiUser === void 0 ? void 0 : apiUser.fullName) || input.fallbackName || '',
19
+ email: asString(apiUser === null || apiUser === void 0 ? void 0 : apiUser.email) || input.fallbackEmail || '',
20
+ attributes: Object.keys(apiAttributes).length > 0
21
+ ? apiAttributes
22
+ : ((_a = input.fallbackAttributes) !== null && _a !== void 0 ? _a : {}),
23
+ document: Object.keys(apiDocument).length > 0 ? apiDocument : ((_b = input.fallbackDocument) !== null && _b !== void 0 ? _b : {}),
24
+ };
25
+ };
26
+ export const toUpdatedUser = (user, userId, attribution, apiUser) => toAppUser({
27
+ apiUser,
28
+ userId,
29
+ fallbackName: user.name,
30
+ fallbackEmail: user.email,
31
+ fallbackAttributes: user.attributes,
32
+ fallbackDocument: withMergedAttributionDocument(user.document, attribution),
33
+ });