@revenuecat/purchases-ui-js 4.8.13 → 4.8.14
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.
|
@@ -83,9 +83,10 @@
|
|
|
83
83
|
// WebView has no visibility overrides; it shows unless visible is explicitly false.
|
|
84
84
|
const isVisible = $derived(props.visible !== false);
|
|
85
85
|
|
|
86
|
-
// Host<->content bridge (client-only):
|
|
87
|
-
//
|
|
88
|
-
// (`resize`), driving `fit` axes; a resolve failure degrades
|
|
86
|
+
// Host<->content bridge (client-only): the host IIFE is loaded from the CDN by
|
|
87
|
+
// protocol version via <script> and attached to the live iframe. The content
|
|
88
|
+
// reports its size (`resize`), driving `fit` axes; a resolve failure degrades
|
|
89
|
+
// to the plain iframe.
|
|
89
90
|
let iframeEl = $state<HTMLIFrameElement | undefined>(undefined);
|
|
90
91
|
let previousSafeUrl: string | null | undefined;
|
|
91
92
|
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Loads `createHostBridge` for the web_view host bridge from the CDN IIFE:
|
|
3
|
+
* `https://sdk.revenuecat-static.com/v<major>/rc-host.iife.js` → `window.RCHost`.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Classic `<script src>` is Metro-safe (no non-literal dynamic `import()`). The
|
|
6
|
+
* ESM sibling at `/v<major>/rc-host.js` remains for other consumers. Types and
|
|
7
|
+
* message constants come from `@revenuecat/workflow-web-components-sdk`.
|
|
7
8
|
*/
|
|
8
|
-
import {
|
|
9
|
+
import type { Bridge, HostBridgeConfig } from "@revenuecat/workflow-web-components-sdk";
|
|
9
10
|
export { FIT_MESSAGE, RESIZE_MESSAGE, } from "@revenuecat/workflow-web-components-sdk";
|
|
10
11
|
export type { ResizePayload } from "@revenuecat/workflow-web-components-sdk";
|
|
12
|
+
/** Base origin the versioned SDK builds are served from. */
|
|
13
|
+
export declare const SDK_BASE_URL = "https://sdk.revenuecat-static.com";
|
|
11
14
|
/**
|
|
12
15
|
* The subset of the SDK bridge purchases-ui-js uses: subscribe to a message, run
|
|
13
16
|
* a callback once the channel opens, fire-and-forget, and tear down.
|
|
@@ -16,20 +19,32 @@ export type WebViewHostBridge = Pick<Bridge, "on" | "onReady" | "send" | "destro
|
|
|
16
19
|
export type CreateHostBridge = (config: HostBridgeConfig) => Bridge;
|
|
17
20
|
/** Test factories may return only the bridge surface this package uses. */
|
|
18
21
|
export type CreateHostBridgeForTests = (config: HostBridgeConfig) => WebViewHostBridge;
|
|
22
|
+
declare global {
|
|
23
|
+
interface Window {
|
|
24
|
+
RCHost?: {
|
|
25
|
+
createHostBridge?: CreateHostBridge;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
type ScriptLoader = (url: string) => Promise<CreateHostBridge>;
|
|
30
|
+
/** Stable, rolling per-major URL of the host bridge IIFE build. */
|
|
31
|
+
export declare function hostSdkUrl(protocolVersion: number): string;
|
|
19
32
|
/**
|
|
20
|
-
* Resolve `createHostBridge` for a protocol major. Rejects on an
|
|
21
|
-
* `protocol_version` so callers can degrade to
|
|
22
|
-
*
|
|
23
|
-
* Today only the bundled npm host implementation is returned (protocol majors
|
|
24
|
-
* share that build). Callers still pass `protocol_version` so the bridge is
|
|
25
|
-
* configured with the component's declared major.
|
|
33
|
+
* Resolve `createHostBridge` for a protocol major from the CDN. Rejects on an
|
|
34
|
+
* invalid `protocol_version` or a failed script load so callers can degrade to
|
|
35
|
+
* a render-only iframe.
|
|
26
36
|
*/
|
|
27
37
|
export declare function loadCreateHostBridge(protocolVersion: number): Promise<CreateHostBridge>;
|
|
28
38
|
/**
|
|
29
39
|
* Override the host-bridge factory. Intended for tests so they never exercise
|
|
30
|
-
* the real postMessage wiring. Pass `null` to restore
|
|
40
|
+
* the real postMessage wiring. Pass `null` to restore CDN loading.
|
|
31
41
|
*/
|
|
32
42
|
export declare function __setCreateHostBridgeForTests(factory: CreateHostBridgeForTests | null): void;
|
|
43
|
+
/**
|
|
44
|
+
* Override the script loader (and clear the cache). Intended for tests that
|
|
45
|
+
* assert the CDN URL without hitting the network.
|
|
46
|
+
*/
|
|
47
|
+
export declare function __setHostScriptLoaderForTests(fn: ScriptLoader | null): void;
|
|
33
48
|
/**
|
|
34
49
|
* Make `loadCreateHostBridge` reject so callers (e.g. WebView) can assert they
|
|
35
50
|
* degrade to a render-only iframe. Pass `null` to clear.
|
|
@@ -1,42 +1,121 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolves `createHostBridge` for the web_view host bridge.
|
|
3
|
-
*
|
|
4
|
-
* Imported statically from `@revenuecat/workflow-web-components-sdk` so this
|
|
5
|
-
* module stays Metro-safe (no non-literal dynamic `import()`). Host version is
|
|
6
|
-
* pinned to the npm dependency until a script-tag CDN loader lands.
|
|
7
|
-
*/
|
|
8
|
-
import { createHostBridge as bundledCreateHostBridge, } from "@revenuecat/workflow-web-components-sdk";
|
|
9
1
|
export { FIT_MESSAGE, RESIZE_MESSAGE, } from "@revenuecat/workflow-web-components-sdk";
|
|
2
|
+
/** Base origin the versioned SDK builds are served from. */
|
|
3
|
+
export const SDK_BASE_URL = "https://sdk.revenuecat-static.com";
|
|
4
|
+
let scriptLoader = loadHostScript;
|
|
10
5
|
let createHostBridgeTestingOverride = null;
|
|
6
|
+
// Memoize per protocol major: the script is stable for the page's lifetime and
|
|
7
|
+
// multiple web views sharing a `protocol_version` should load it once.
|
|
8
|
+
const moduleCache = new Map();
|
|
9
|
+
/** Stable, rolling per-major URL of the host bridge IIFE build. */
|
|
10
|
+
export function hostSdkUrl(protocolVersion) {
|
|
11
|
+
return `${SDK_BASE_URL}/v${protocolVersion}/rc-host.iife.js`;
|
|
12
|
+
}
|
|
11
13
|
function assertValidProtocolVersion(protocolVersion) {
|
|
12
14
|
if (!Number.isInteger(protocolVersion) || protocolVersion < 1) {
|
|
13
15
|
throw new Error(`invalid web_view protocol_version: ${protocolVersion}`);
|
|
14
16
|
}
|
|
15
17
|
}
|
|
18
|
+
function readCreateHostBridge(url) {
|
|
19
|
+
const factory = window.RCHost?.createHostBridge;
|
|
20
|
+
if (typeof factory !== "function") {
|
|
21
|
+
throw new Error(`rc-host.iife.js at ${url} did not register window.RCHost.createHostBridge`);
|
|
22
|
+
}
|
|
23
|
+
return factory;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Load the CDN IIFE via a classic `<script>` tag and resolve
|
|
27
|
+
* `window.RCHost.createHostBridge`.
|
|
28
|
+
*/
|
|
29
|
+
function loadHostScript(url) {
|
|
30
|
+
if (typeof document === "undefined") {
|
|
31
|
+
return Promise.reject(new Error("web_view host bridge requires a document to load the CDN script"));
|
|
32
|
+
}
|
|
33
|
+
if (typeof window.RCHost?.createHostBridge === "function") {
|
|
34
|
+
return Promise.resolve(readCreateHostBridge(url));
|
|
35
|
+
}
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
const existing = document.querySelector(`script[data-rc-host-sdk="${url.replace(/"/g, '\\"')}"]`);
|
|
38
|
+
if (existing) {
|
|
39
|
+
const settle = () => {
|
|
40
|
+
try {
|
|
41
|
+
resolve(readCreateHostBridge(url));
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
reject(error);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
if (typeof window.RCHost?.createHostBridge === "function") {
|
|
48
|
+
settle();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
existing.addEventListener("load", settle);
|
|
52
|
+
existing.addEventListener("error", () => {
|
|
53
|
+
reject(new Error(`failed to load ${url}`));
|
|
54
|
+
});
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const script = document.createElement("script");
|
|
58
|
+
script.src = url;
|
|
59
|
+
script.async = true;
|
|
60
|
+
script.dataset.rcHostSdk = url;
|
|
61
|
+
script.onload = () => {
|
|
62
|
+
try {
|
|
63
|
+
resolve(readCreateHostBridge(url));
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
reject(error);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
script.onerror = () => {
|
|
70
|
+
reject(new Error(`failed to load ${url}`));
|
|
71
|
+
};
|
|
72
|
+
document.head.appendChild(script);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function resolveHostFactory(protocolVersion) {
|
|
76
|
+
const cached = moduleCache.get(protocolVersion);
|
|
77
|
+
if (cached)
|
|
78
|
+
return cached;
|
|
79
|
+
const url = hostSdkUrl(protocolVersion);
|
|
80
|
+
const promise = scriptLoader(url);
|
|
81
|
+
promise.catch(() => {
|
|
82
|
+
if (moduleCache.get(protocolVersion) === promise) {
|
|
83
|
+
moduleCache.delete(protocolVersion);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
moduleCache.set(protocolVersion, promise);
|
|
87
|
+
return promise;
|
|
88
|
+
}
|
|
16
89
|
/**
|
|
17
|
-
* Resolve `createHostBridge` for a protocol major. Rejects on an
|
|
18
|
-
* `protocol_version` so callers can degrade to
|
|
19
|
-
*
|
|
20
|
-
* Today only the bundled npm host implementation is returned (protocol majors
|
|
21
|
-
* share that build). Callers still pass `protocol_version` so the bridge is
|
|
22
|
-
* configured with the component's declared major.
|
|
90
|
+
* Resolve `createHostBridge` for a protocol major from the CDN. Rejects on an
|
|
91
|
+
* invalid `protocol_version` or a failed script load so callers can degrade to
|
|
92
|
+
* a render-only iframe.
|
|
23
93
|
*/
|
|
24
94
|
export async function loadCreateHostBridge(protocolVersion) {
|
|
25
95
|
assertValidProtocolVersion(protocolVersion);
|
|
26
96
|
if (createHostBridgeTestingOverride) {
|
|
27
97
|
return createHostBridgeTestingOverride();
|
|
28
98
|
}
|
|
29
|
-
return
|
|
99
|
+
return resolveHostFactory(protocolVersion);
|
|
30
100
|
}
|
|
31
101
|
/**
|
|
32
102
|
* Override the host-bridge factory. Intended for tests so they never exercise
|
|
33
|
-
* the real postMessage wiring. Pass `null` to restore
|
|
103
|
+
* the real postMessage wiring. Pass `null` to restore CDN loading.
|
|
34
104
|
*/
|
|
35
105
|
export function __setCreateHostBridgeForTests(factory) {
|
|
36
106
|
createHostBridgeTestingOverride = factory
|
|
37
107
|
? // Test stubs only implement the WebViewHostBridge surface.
|
|
38
108
|
async () => factory
|
|
39
109
|
: null;
|
|
110
|
+
moduleCache.clear();
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Override the script loader (and clear the cache). Intended for tests that
|
|
114
|
+
* assert the CDN URL without hitting the network.
|
|
115
|
+
*/
|
|
116
|
+
export function __setHostScriptLoaderForTests(fn) {
|
|
117
|
+
scriptLoader = fn ?? loadHostScript;
|
|
118
|
+
moduleCache.clear();
|
|
40
119
|
}
|
|
41
120
|
/**
|
|
42
121
|
* Make `loadCreateHostBridge` reject so callers (e.g. WebView) can assert they
|
|
@@ -48,4 +127,5 @@ export function __failCreateHostBridgeForTests(error) {
|
|
|
48
127
|
throw error;
|
|
49
128
|
}
|
|
50
129
|
: null;
|
|
130
|
+
moduleCache.clear();
|
|
51
131
|
}
|