@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.
- package/dist/config/env.config.d.ts +0 -2
- package/dist/config/env.config.js +0 -4
- package/dist/runtime/posthog-flags.d.ts +4 -0
- package/dist/runtime/posthog-flags.js +3 -2
- package/dist/runtime/use-funnel-flow-controller.d.ts +5 -1
- package/dist/runtime/use-funnel-flow-controller.js +16 -2
- package/dist/services/funnel-runtime-config.d.ts +11 -0
- package/dist/services/funnel-runtime-config.js +15 -0
- package/dist/services/project-env.d.ts +0 -2
- package/dist/services/project-env.js +0 -4
- package/dist/services/public-env.d.ts +0 -4
- package/dist/services/public-env.js +0 -5
- package/package.json +1 -1
|
@@ -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 =
|
|
89
|
-
&& shouldRecordPostHogSession(config.distinctId,
|
|
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
|
-
}, [
|
|
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) ||
|