@funnelsgrove/runtime 0.7.8 → 0.7.9
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.
|
@@ -13,6 +13,7 @@ type FunnelRuntimeConfigBoundaryProps = {
|
|
|
13
13
|
errorFallback?: ReactNode;
|
|
14
14
|
disabled?: boolean;
|
|
15
15
|
};
|
|
16
|
+
export declare const FUNNEL_RUNTIME_CONFIG_REFRESH_INTERVAL_MS = 5000;
|
|
16
17
|
export declare function FunnelRuntimeConfigBoundary({ disabled, ...props }: FunnelRuntimeConfigBoundaryProps): import("react/jsx-runtime").JSX.Element;
|
|
17
18
|
export declare const useFunnelRuntimeConfig: () => FunnelRuntimeConfigState;
|
|
18
19
|
export {};
|
|
@@ -18,14 +18,12 @@ const FunnelRuntimeConfigContext = createContext({
|
|
|
18
18
|
config: null,
|
|
19
19
|
error: null,
|
|
20
20
|
});
|
|
21
|
+
export const FUNNEL_RUNTIME_CONFIG_REFRESH_INTERVAL_MS = 5000;
|
|
21
22
|
const toError = (value) => (value instanceof Error ? value : new Error('Unable to load funnel runtime config'));
|
|
22
23
|
/**
|
|
23
|
-
* Loads the
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* A published funnel never falls back to generated pricing or experiment
|
|
28
|
-
* config: the version-bound artifact is its single source of truth.
|
|
24
|
+
* Loads the latest publication before mount and then follows config-only
|
|
25
|
+
* publications for the same source funnel version. Each resolved snapshot is
|
|
26
|
+
* deeply frozen; publication revisions are the only supported update boundary.
|
|
29
27
|
*/
|
|
30
28
|
function ActiveFunnelRuntimeConfigBoundary({ funnelId, funnelVersionId, children, loadingFallback = null, errorFallback = null, }) {
|
|
31
29
|
const [state, setState] = useState({
|
|
@@ -35,22 +33,37 @@ function ActiveFunnelRuntimeConfigBoundary({ funnelId, funnelVersionId, children
|
|
|
35
33
|
});
|
|
36
34
|
useEffect(() => {
|
|
37
35
|
let active = true;
|
|
38
|
-
|
|
36
|
+
let refreshTimer = null;
|
|
37
|
+
const refresh = () => loadFunnelRuntimeConfig(funnelId, { versionId: funnelVersionId })
|
|
39
38
|
.then((published) => resolvePublishedFunnelRuntimeConfig(published, {
|
|
40
39
|
expectedFunnelVersionId: funnelVersionId,
|
|
41
40
|
}))
|
|
42
41
|
.then((config) => {
|
|
43
|
-
if (active)
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
if (!active)
|
|
43
|
+
return;
|
|
44
|
+
setState((current) => {
|
|
45
|
+
var _a;
|
|
46
|
+
return (current.status === 'published' && ((_a = current.config) === null || _a === void 0 ? void 0 : _a.revisionId) === config.revisionId
|
|
47
|
+
? current
|
|
48
|
+
: { status: 'published', config, error: null });
|
|
49
|
+
});
|
|
46
50
|
})
|
|
47
51
|
.catch((error) => {
|
|
52
|
+
if (!active)
|
|
53
|
+
return;
|
|
54
|
+
setState((current) => (current.status === 'published'
|
|
55
|
+
? current
|
|
56
|
+
: { status: 'fallback', config: null, error: toError(error) }));
|
|
57
|
+
});
|
|
58
|
+
void refresh().then(() => {
|
|
48
59
|
if (active) {
|
|
49
|
-
|
|
60
|
+
refreshTimer = setInterval(() => void refresh(), FUNNEL_RUNTIME_CONFIG_REFRESH_INTERVAL_MS);
|
|
50
61
|
}
|
|
51
62
|
});
|
|
52
63
|
return () => {
|
|
53
64
|
active = false;
|
|
65
|
+
if (refreshTimer)
|
|
66
|
+
clearInterval(refreshTimer);
|
|
54
67
|
};
|
|
55
68
|
}, [funnelId, funnelVersionId]);
|
|
56
69
|
const contextValue = useMemo(() => state, [state]);
|
|
@@ -259,7 +259,8 @@ export const loadFunnelRuntimeConfig = (funnelId, options = {}) => {
|
|
|
259
259
|
const fetcher = options.fetcher || globalThis.fetch;
|
|
260
260
|
const basePath = (options.basePath || '/api/funnel-config').replace(/\/$/, '');
|
|
261
261
|
const request = fetcher(`${basePath}/${encodeURIComponent(normalizedFunnelId)}?versionId=${encodeURIComponent(versionId)}`, {
|
|
262
|
-
|
|
262
|
+
cache: 'no-store',
|
|
263
|
+
headers: { accept: 'application/json', 'cache-control': 'no-cache' },
|
|
263
264
|
}).then(async (response) => {
|
|
264
265
|
if (!response.ok) {
|
|
265
266
|
throw new Error(`Unable to load funnel runtime config (${response.status})`);
|