@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.
- package/README.md +51 -0
- package/dist/components/ManageSubscriptionScreen.js +7 -2
- package/dist/services/api.service.d.ts +28 -104
- package/dist/services/api.service.js +24 -519
- package/dist/services/funnel-sdk/checkout/chargeOneClickPayment.d.ts +2 -0
- package/dist/services/funnel-sdk/checkout/chargeOneClickPayment.js +17 -0
- package/dist/services/funnel-sdk/checkout/createHostedCheckoutSession.d.ts +2 -0
- package/dist/services/funnel-sdk/checkout/createHostedCheckoutSession.js +9 -0
- package/dist/services/funnel-sdk/checkout/createOneTimeCheckout.d.ts +2 -0
- package/dist/services/funnel-sdk/checkout/createOneTimeCheckout.js +18 -0
- package/dist/services/funnel-sdk/checkout/createOneTimePaymentIntent.d.ts +3 -0
- package/dist/services/funnel-sdk/checkout/createOneTimePaymentIntent.js +10 -0
- package/dist/services/funnel-sdk/checkout/createSubscriptionCheckout.d.ts +2 -0
- package/dist/services/funnel-sdk/checkout/createSubscriptionCheckout.js +19 -0
- package/dist/services/funnel-sdk/checkout/requests.d.ts +126 -0
- package/dist/services/funnel-sdk/checkout/requests.js +111 -0
- package/dist/services/funnel-sdk/checkout/types.d.ts +183 -0
- package/dist/services/funnel-sdk/checkout/types.js +1 -0
- package/dist/services/funnel-sdk/checkout/updateSubscriptionCheckoutPlan.d.ts +2 -0
- package/dist/services/funnel-sdk/checkout/updateSubscriptionCheckoutPlan.js +18 -0
- package/dist/services/funnel-sdk/checkout/verifySubscriptionCheckout.d.ts +2 -0
- package/dist/services/funnel-sdk/checkout/verifySubscriptionCheckout.js +18 -0
- package/dist/services/funnel-sdk/shared/http.d.ts +20 -0
- package/dist/services/funnel-sdk/shared/http.js +65 -0
- package/dist/services/funnel-sdk/shared/runtimeConfig.d.ts +17 -0
- package/dist/services/funnel-sdk/shared/runtimeConfig.js +42 -0
- package/dist/services/funnel-sdk/shared/types.d.ts +9 -0
- package/dist/services/funnel-sdk/shared/types.js +1 -0
- package/dist/services/funnel-sdk/subscriptions/listSubscriptions.d.ts +3 -0
- package/dist/services/funnel-sdk/subscriptions/listSubscriptions.js +17 -0
- package/dist/services/funnel-sdk/subscriptions/types.d.ts +24 -0
- package/dist/services/funnel-sdk/subscriptions/types.js +1 -0
- package/dist/services/funnel-sdk/subscriptions/updateSubscription.d.ts +2 -0
- package/dist/services/funnel-sdk/subscriptions/updateSubscription.js +33 -0
- package/dist/services/funnel-sdk/subscriptions/validator.d.ts +2 -0
- package/dist/services/funnel-sdk/subscriptions/validator.js +15 -0
- package/dist/services/funnel-sdk/uploads/preparePhotoUpload.d.ts +4 -0
- package/dist/services/funnel-sdk/uploads/preparePhotoUpload.js +19 -0
- package/dist/services/funnel-sdk/uploads/types.d.ts +32 -0
- package/dist/services/funnel-sdk/uploads/types.js +1 -0
- package/dist/services/funnel-sdk/uploads/uploadPhoto.d.ts +7 -0
- package/dist/services/funnel-sdk/uploads/uploadPhoto.js +18 -0
- package/dist/services/funnel-sdk/uploads/uploadPhotoFile.d.ts +2 -0
- package/dist/services/funnel-sdk/uploads/uploadPhotoFile.js +26 -0
- package/dist/services/funnel-sdk/users/bootstrapUser.d.ts +3 -0
- package/dist/services/funnel-sdk/users/bootstrapUser.js +15 -0
- package/dist/services/funnel-sdk/users/captureEmail.d.ts +2 -0
- package/dist/services/funnel-sdk/users/captureEmail.js +15 -0
- package/dist/services/funnel-sdk/users/claimUserSubscription.d.ts +3 -0
- package/dist/services/funnel-sdk/users/claimUserSubscription.js +7 -0
- package/dist/services/funnel-sdk/users/getCurrentUser.d.ts +3 -0
- package/dist/services/funnel-sdk/users/getCurrentUser.js +13 -0
- package/dist/services/funnel-sdk/users/getUserSubscriptionStatus.d.ts +3 -0
- package/dist/services/funnel-sdk/users/getUserSubscriptionStatus.js +14 -0
- package/dist/services/funnel-sdk/users/types.d.ts +57 -0
- package/dist/services/funnel-sdk/users/types.js +1 -0
- package/dist/services/funnel-sdk/users/updateFunnelUser.d.ts +3 -0
- package/dist/services/funnel-sdk/users/updateFunnelUser.js +18 -0
- package/dist/services/funnel-sdk.service.d.ts +26 -319
- package/dist/services/funnel-sdk.service.js +38 -456
- package/dist/services/session/bootstrap/bootstrapSession.d.ts +8 -0
- package/dist/services/session/bootstrap/bootstrapSession.js +23 -0
- package/dist/services/session/bootstrap/currentUser.d.ts +1 -0
- package/dist/services/session/bootstrap/currentUser.js +37 -0
- package/dist/services/session/bootstrap/idempotency.d.ts +9 -0
- package/dist/services/session/bootstrap/idempotency.js +97 -0
- package/dist/services/session/bootstrap/requests.d.ts +23 -0
- package/dist/services/session/bootstrap/requests.js +25 -0
- package/dist/services/session/bootstrap/responses.d.ts +3 -0
- package/dist/services/session/bootstrap/responses.js +10 -0
- package/dist/services/session/bootstrap/types.d.ts +11 -0
- package/dist/services/session/bootstrap/types.js +1 -0
- package/dist/services/session/emailCapture/captureEmail.d.ts +8 -0
- package/dist/services/session/emailCapture/captureEmail.js +13 -0
- package/dist/services/session/emailCapture/requests.d.ts +12 -0
- package/dist/services/session/emailCapture/requests.js +6 -0
- package/dist/services/session/emailCapture/responses.d.ts +3 -0
- package/dist/services/session/emailCapture/responses.js +14 -0
- package/dist/services/session/emailCapture/types.d.ts +8 -0
- package/dist/services/session/emailCapture/types.js +1 -0
- package/dist/services/session/emailCapture/validator.d.ts +16 -0
- package/dist/services/session/emailCapture/validator.js +37 -0
- package/dist/services/session/identity.d.ts +6 -0
- package/dist/services/session/identity.js +48 -0
- package/dist/services/session/ping/pingUserContext.d.ts +2 -0
- package/dist/services/session/ping/pingUserContext.js +10 -0
- package/dist/services/session/ping/transport.d.ts +2 -0
- package/dist/services/session/ping/transport.js +41 -0
- package/dist/services/session/shared/values.d.ts +6 -0
- package/dist/services/session/shared/values.js +25 -0
- package/dist/services/session/subscriptions/getManageSubscriptions.d.ts +3 -0
- package/dist/services/session/subscriptions/getManageSubscriptions.js +8 -0
- package/dist/services/session/subscriptions/identity.d.ts +3 -0
- package/dist/services/session/subscriptions/identity.js +8 -0
- package/dist/services/session/subscriptions/types.d.ts +35 -0
- package/dist/services/session/subscriptions/types.js +1 -0
- package/dist/services/session/subscriptions/updateSubscription.d.ts +10 -0
- package/dist/services/session/subscriptions/updateSubscription.js +7 -0
- package/dist/services/session/subscriptions/validator.d.ts +6 -0
- package/dist/services/session/subscriptions/validator.js +13 -0
- package/dist/services/session/uploads/localPhoto.d.ts +2 -0
- package/dist/services/session/uploads/localPhoto.js +10 -0
- package/dist/services/session/uploads/requests.d.ts +10 -0
- package/dist/services/session/uploads/requests.js +7 -0
- package/dist/services/session/uploads/types.d.ts +7 -0
- package/dist/services/session/uploads/types.js +1 -0
- package/dist/services/session/uploads/uploadTempPhoto.d.ts +6 -0
- package/dist/services/session/uploads/uploadTempPhoto.js +13 -0
- package/dist/services/session/uploads/validator.d.ts +3 -0
- package/dist/services/session/uploads/validator.js +12 -0
- package/dist/services/session/users/mappers.d.ts +13 -0
- package/dist/services/session/users/mappers.js +33 -0
- package/dist/services/session/users/requests.d.ts +15 -0
- package/dist/services/session/users/requests.js +8 -0
- package/dist/services/session/users/syncUrlUserAttributes.d.ts +10 -0
- package/dist/services/session/users/syncUrlUserAttributes.js +21 -0
- package/dist/services/session/users/types.d.ts +20 -0
- package/dist/services/session/users/types.js +1 -0
- package/dist/services/session/users/updateUser.d.ts +6 -0
- package/dist/services/session/users/updateUser.js +18 -0
- package/package.json +1 -1
- /package/dist/services/{funnel-sdk-payments.functions.d.ts → funnel-sdk/checkout/selection.d.ts} +0 -0
- /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,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 @@
|
|
|
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,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,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,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 @@
|
|
|
1
|
+
export {};
|
|
@@ -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,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
|
+
});
|