@applicaster/quick-brick-core 15.1.5-alpha.7597480209 → 15.1.5-rc.1
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/App/ActionSetters/index.ts +20 -32
- package/App/remoteContextReloader/getRemoteContextData/getLegacyRemoteContextData.ts +19 -25
- package/App/remoteContextReloader/getRemoteContextData/getNativeRemoteContextData.ts +0 -22
- package/App/remoteContextReloader/helpers.ts +34 -127
- package/package.json +8 -8
- package/App/remoteContextReloader/cachedRemoteJson.ts +0 -37
|
@@ -20,6 +20,10 @@ const warnUndefinedContext = (context) =>
|
|
|
20
20
|
data: { context },
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
+
type Subscription = {
|
|
24
|
+
[x: string]: () => any;
|
|
25
|
+
};
|
|
26
|
+
|
|
23
27
|
const getModuleContext = R.path(["module", "context"]);
|
|
24
28
|
|
|
25
29
|
const getContexts = R.compose(
|
|
@@ -59,40 +63,24 @@ const useSubscribeToActionProviders = () => {
|
|
|
59
63
|
export const useRiverInitialState = () => {
|
|
60
64
|
const key = "getRiverInitialState";
|
|
61
65
|
const actionProvidersSubscriptions = useSubscribeToActionProviders();
|
|
62
|
-
// Capture river-init promises once. Re-calling getRiverInitialState() on every
|
|
63
|
-
// context re-render causes thrash and can drop already-completed observables.
|
|
64
|
-
// Plugins should return Promise.resolve() when already initialized (not undefined).
|
|
65
|
-
const capturedPromisesRef = React.useRef<Promise<unknown>[] | null>(null);
|
|
66
|
-
|
|
67
|
-
if (
|
|
68
|
-
capturedPromisesRef.current === null &&
|
|
69
|
-
actionProvidersSubscriptions.length > 0
|
|
70
|
-
) {
|
|
71
|
-
const providersWithMethod = actionProvidersSubscriptions.filter(
|
|
72
|
-
(item) => item?.[key]
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
const promises = providersWithMethod
|
|
76
|
-
.map((item) => item[key]())
|
|
77
|
-
.filter(Boolean) as Promise<unknown>[];
|
|
78
|
-
|
|
79
|
-
// Lock when every river-init provider returned a promise, or none expose it.
|
|
80
|
-
// Retry while a provider still returns undefined (getInitialState not started).
|
|
81
|
-
if (
|
|
82
|
-
providersWithMethod.length === 0 ||
|
|
83
|
-
promises.length === providersWithMethod.length
|
|
84
|
-
) {
|
|
85
|
-
capturedPromisesRef.current = promises;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
66
|
|
|
89
|
-
|
|
90
|
-
return undefined;
|
|
91
|
-
|
|
67
|
+
const subscriptions = React.useMemo(() => {
|
|
68
|
+
if (!actionProvidersSubscriptions.length) return undefined;
|
|
69
|
+
|
|
70
|
+
return actionProvidersSubscriptions.reduce((acc, item) => {
|
|
71
|
+
const riverInitialStatePromise = item[key]?.();
|
|
92
72
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
73
|
+
if (riverInitialStatePromise) {
|
|
74
|
+
acc.push(riverInitialStatePromise);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return acc;
|
|
78
|
+
}, [] as Subscription[]);
|
|
79
|
+
}, [actionProvidersSubscriptions]);
|
|
80
|
+
|
|
81
|
+
if (!actionProvidersSubscriptions.length) return undefined;
|
|
82
|
+
|
|
83
|
+
return subscriptions;
|
|
96
84
|
};
|
|
97
85
|
|
|
98
86
|
const getActionInitialStateSetters = (key) => {
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import * as R from "ramda";
|
|
2
2
|
import { loadAppContextData } from "@applicaster/zapp-react-native-redux";
|
|
3
3
|
|
|
4
|
+
import { URL_KEYS } from "../consts";
|
|
4
5
|
import {
|
|
5
6
|
fetchPluginConfiguration,
|
|
6
|
-
|
|
7
|
+
getPromiseForKey,
|
|
8
|
+
prepareRuntimeConfigurationUrls,
|
|
7
9
|
} from "../helpers";
|
|
8
10
|
import { isTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
9
11
|
import { Dimensions } from "react-native";
|
|
10
12
|
import { cacheAssets } from "../../AssetCache";
|
|
11
|
-
import { logger } from "@applicaster/zapp-react-native-utils/logger";
|
|
12
13
|
|
|
13
14
|
const buildContextData = (remoteData) => {
|
|
14
15
|
const { width, height } = Dimensions.get("window");
|
|
@@ -32,18 +33,6 @@ export async function getLegacyRemoteContextData(
|
|
|
32
33
|
runtimeConfigurationUrls,
|
|
33
34
|
plugins
|
|
34
35
|
) {
|
|
35
|
-
const t0 = performance.now();
|
|
36
|
-
|
|
37
|
-
const mark = (label: string) => {
|
|
38
|
-
logger.log({
|
|
39
|
-
message: `[PERF][remote] ${label} +${Math.round(
|
|
40
|
-
performance.now() - t0
|
|
41
|
-
)}ms`,
|
|
42
|
-
});
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
mark("start");
|
|
46
|
-
|
|
47
36
|
const layoutManagerPlugin = R.find(
|
|
48
37
|
R.pathSatisfies(R.is(Function), ["module", "selectLayout"])
|
|
49
38
|
)(plugins);
|
|
@@ -61,16 +50,25 @@ export async function getLegacyRemoteContextData(
|
|
|
61
50
|
isTablet: isTabletDevice,
|
|
62
51
|
});
|
|
63
52
|
|
|
64
|
-
|
|
53
|
+
const { preparedRuntimeConfigurationUrls, layoutData = [] } =
|
|
54
|
+
await prepareRuntimeConfigurationUrls(
|
|
55
|
+
configurationUrls || runtimeConfigurationUrls,
|
|
56
|
+
isTabletDevice
|
|
57
|
+
);
|
|
65
58
|
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
59
|
+
const promises = R.compose(
|
|
60
|
+
R.map(getPromiseForKey(preparedRuntimeConfigurationUrls)),
|
|
61
|
+
R.reject(R.isNil),
|
|
62
|
+
R.keys,
|
|
63
|
+
R.pick(URL_KEYS)
|
|
64
|
+
)(preparedRuntimeConfigurationUrls);
|
|
70
65
|
|
|
71
|
-
|
|
66
|
+
const resolvedPromises = await Promise.all(promises);
|
|
72
67
|
|
|
73
|
-
const remoteData =
|
|
68
|
+
const remoteData = R.compose(
|
|
69
|
+
buildContextData,
|
|
70
|
+
R.mergeAll
|
|
71
|
+
)([...layoutData, ...resolvedPromises]);
|
|
74
72
|
|
|
75
73
|
const useTabletLayout =
|
|
76
74
|
isTabletDevice &&
|
|
@@ -85,8 +83,6 @@ export async function getLegacyRemoteContextData(
|
|
|
85
83
|
: remoteData.cellStyles,
|
|
86
84
|
});
|
|
87
85
|
|
|
88
|
-
mark("cacheAssets done");
|
|
89
|
-
|
|
90
86
|
const { pluginConfigurations } = cachedRemoteData;
|
|
91
87
|
|
|
92
88
|
const updatedPlugins = R.map(
|
|
@@ -109,6 +105,4 @@ export async function getLegacyRemoteContextData(
|
|
|
109
105
|
...appProperties,
|
|
110
106
|
plugins: updatedPlugins,
|
|
111
107
|
});
|
|
112
|
-
|
|
113
|
-
mark("loadAppContextData done");
|
|
114
108
|
}
|
|
@@ -20,18 +20,6 @@ export async function getNativeRemoteContextData(
|
|
|
20
20
|
runtimeConfigurationUrls,
|
|
21
21
|
plugins
|
|
22
22
|
) {
|
|
23
|
-
const t0 = performance.now();
|
|
24
|
-
|
|
25
|
-
const mark = (label: string) => {
|
|
26
|
-
logger.log({
|
|
27
|
-
message: `[PERF][remote-native] ${label} +${Math.round(
|
|
28
|
-
performance.now() - t0
|
|
29
|
-
)}ms`,
|
|
30
|
-
});
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
mark("start");
|
|
34
|
-
|
|
35
23
|
const { width, height } = Dimensions.get("window");
|
|
36
24
|
|
|
37
25
|
const isTabletDevice = isTablet(
|
|
@@ -45,8 +33,6 @@ export async function getNativeRemoteContextData(
|
|
|
45
33
|
"pipesEndpoints",
|
|
46
34
|
]);
|
|
47
35
|
|
|
48
|
-
mark("generalConfiguration done");
|
|
49
|
-
|
|
50
36
|
loadAppContextData(dispatch, R.mergeAll([...generalConfiguration]));
|
|
51
37
|
|
|
52
38
|
try {
|
|
@@ -74,10 +60,7 @@ export async function getNativeRemoteContextData(
|
|
|
74
60
|
});
|
|
75
61
|
}
|
|
76
62
|
|
|
77
|
-
mark("selectLayout done");
|
|
78
|
-
|
|
79
63
|
const layout = await getPromiseForType("layout");
|
|
80
|
-
mark("layout done");
|
|
81
64
|
|
|
82
65
|
const layoutLoadingErrorMessage = "Failed to load layout data";
|
|
83
66
|
|
|
@@ -96,7 +79,6 @@ export async function getNativeRemoteContextData(
|
|
|
96
79
|
dispatch(AppData.actions.merge({ layoutVersion: apiVersion || "v1" }));
|
|
97
80
|
|
|
98
81
|
const resolvedPromises = await mapPromises(getPromiseForType, ["cellStyles"]);
|
|
99
|
-
mark("cellStyles done");
|
|
100
82
|
|
|
101
83
|
let optionalResolvedPromise;
|
|
102
84
|
|
|
@@ -120,8 +102,6 @@ export async function getNativeRemoteContextData(
|
|
|
120
102
|
cellStyles: remoteData.cellStyles,
|
|
121
103
|
});
|
|
122
104
|
|
|
123
|
-
mark("cacheAssets done");
|
|
124
|
-
|
|
125
105
|
const { pluginConfigurations } = cachedRemoteData;
|
|
126
106
|
|
|
127
107
|
const updatedPlugins = R.map(
|
|
@@ -146,6 +126,4 @@ export async function getNativeRemoteContextData(
|
|
|
146
126
|
...appProperties,
|
|
147
127
|
plugins: updatedPlugins,
|
|
148
128
|
});
|
|
149
|
-
|
|
150
|
-
mark("loadAppContextData done");
|
|
151
129
|
}
|
|
@@ -2,9 +2,8 @@ import axios from "axios";
|
|
|
2
2
|
import camelize from "camelize";
|
|
3
3
|
import * as R from "ramda";
|
|
4
4
|
import { NativeModules } from "react-native";
|
|
5
|
-
import { URL_KEY_SUFFIX
|
|
5
|
+
import { URL_KEY_SUFFIX } from "./consts";
|
|
6
6
|
import { sessionStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/SessionStorage";
|
|
7
|
-
import { cachedRemoteJson } from "./cachedRemoteJson";
|
|
8
7
|
|
|
9
8
|
const { AppLoaderBridge } = NativeModules;
|
|
10
9
|
|
|
@@ -28,125 +27,23 @@ export const urlKeyToContext = R.compose(
|
|
|
28
27
|
R.replace(URL_KEY_SUFFIX, "")
|
|
29
28
|
);
|
|
30
29
|
|
|
31
|
-
function stripOppositePlatformUrls(runtimeConfigurationUrls, isTablet) {
|
|
32
|
-
const preparedRuntimeConfigurationUrls = { ...runtimeConfigurationUrls };
|
|
33
|
-
|
|
34
|
-
if (isTablet) {
|
|
35
|
-
if (preparedRuntimeConfigurationUrls[REMOTE_CONFIG_KEYS.TABLET.LAYOUT]) {
|
|
36
|
-
delete preparedRuntimeConfigurationUrls[REMOTE_CONFIG_KEYS.MOBILE.LAYOUT];
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
preparedRuntimeConfigurationUrls[REMOTE_CONFIG_KEYS.TABLET.CELL_STYLES]
|
|
41
|
-
) {
|
|
42
|
-
delete preparedRuntimeConfigurationUrls[
|
|
43
|
-
REMOTE_CONFIG_KEYS.MOBILE.CELL_STYLES
|
|
44
|
-
];
|
|
45
|
-
}
|
|
46
|
-
} else {
|
|
47
|
-
delete preparedRuntimeConfigurationUrls[REMOTE_CONFIG_KEYS.TABLET.LAYOUT];
|
|
48
|
-
|
|
49
|
-
delete preparedRuntimeConfigurationUrls[
|
|
50
|
-
REMOTE_CONFIG_KEYS.TABLET.CELL_STYLES
|
|
51
|
-
];
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return preparedRuntimeConfigurationUrls;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async function fetchJsonByUrlKey(runtimeConfigurationUrls, urlKey) {
|
|
58
|
-
const context = urlKeyToContext(urlKey);
|
|
59
|
-
const url = R.prop(urlKey, runtimeConfigurationUrls);
|
|
60
|
-
|
|
61
|
-
try {
|
|
62
|
-
const data = await cachedRemoteJson(url, async () => {
|
|
63
|
-
const response = await axios.get(url);
|
|
64
|
-
|
|
65
|
-
return response.data;
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
[context]: data,
|
|
70
|
-
};
|
|
71
|
-
} catch (e) {
|
|
72
|
-
throw new Error("cannot retrieve configuration data for " + urlKey);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
30
|
export function getPromiseForKey(runtimeConfigurationUrls) {
|
|
77
31
|
return async function (urlKey) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Fetches layout + remaining remote JSON in parallel.
|
|
84
|
-
* If cell_styles URL is out of sync with layout.id, refetches cells only.
|
|
85
|
-
*/
|
|
86
|
-
export async function fetchAllRemoteConfigurations(
|
|
87
|
-
runtimeConfigurationUrls,
|
|
88
|
-
isTablet
|
|
89
|
-
) {
|
|
90
|
-
const layoutUrlKey = isTablet
|
|
91
|
-
? REMOTE_CONFIG_KEYS.TABLET.LAYOUT
|
|
92
|
-
: REMOTE_CONFIG_KEYS.MOBILE.LAYOUT;
|
|
32
|
+
const context = urlKeyToContext(urlKey);
|
|
33
|
+
const url = R.prop(urlKey, runtimeConfigurationUrls);
|
|
93
34
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
: REMOTE_CONFIG_KEYS.MOBILE.CELL_STYLES;
|
|
97
|
-
|
|
98
|
-
const layoutUrl = R.prop(layoutUrlKey, runtimeConfigurationUrls);
|
|
99
|
-
const cellStylesUrl = R.prop(cellStylesUrlKey, runtimeConfigurationUrls);
|
|
100
|
-
const layoutContext = urlKeyToContext(layoutUrlKey);
|
|
101
|
-
const cellStylesContext = urlKeyToContext(cellStylesUrlKey);
|
|
102
|
-
|
|
103
|
-
const preparedRuntimeConfigurationUrls = stripOppositePlatformUrls(
|
|
104
|
-
runtimeConfigurationUrls,
|
|
105
|
-
isTablet
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
const keys = R.compose(
|
|
109
|
-
R.reject(R.isNil),
|
|
110
|
-
R.keys,
|
|
111
|
-
R.pick(URL_KEYS)
|
|
112
|
-
)(preparedRuntimeConfigurationUrls);
|
|
113
|
-
|
|
114
|
-
if (!layoutUrl) {
|
|
115
|
-
const resolvedPromises = await Promise.all(
|
|
116
|
-
keys.map(getPromiseForKey(preparedRuntimeConfigurationUrls))
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
return R.mergeAll(resolvedPromises);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const resolvedPromises = await Promise.all(
|
|
123
|
-
keys.map(getPromiseForKey(preparedRuntimeConfigurationUrls))
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
const remoteData = R.mergeAll(resolvedPromises);
|
|
127
|
-
const layout = remoteData[layoutContext];
|
|
128
|
-
const layoutId = layout?.id;
|
|
129
|
-
|
|
130
|
-
if (cellStylesUrl && layoutId && !cellStylesUrl.includes(layoutId)) {
|
|
131
|
-
const splitedUrl = cellStylesUrl.split("/");
|
|
132
|
-
const oldLayoutId = splitedUrl[splitedUrl.length - 2];
|
|
133
|
-
const correctedUrl = cellStylesUrl.replace(oldLayoutId, layoutId);
|
|
134
|
-
|
|
135
|
-
await sessionStorage.setItem("rivers_configuration_id", layoutId);
|
|
136
|
-
|
|
137
|
-
const cellStyles = await cachedRemoteJson(correctedUrl, async () => {
|
|
138
|
-
const response = await axios.get(correctedUrl);
|
|
139
|
-
|
|
140
|
-
return response.data;
|
|
141
|
-
});
|
|
35
|
+
try {
|
|
36
|
+
const response = await axios.get(url);
|
|
142
37
|
|
|
143
|
-
|
|
144
|
-
...remoteData,
|
|
145
|
-
[cellStylesContext]: cellStyles,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
38
|
+
const { data } = response;
|
|
148
39
|
|
|
149
|
-
|
|
40
|
+
return {
|
|
41
|
+
[context]: data,
|
|
42
|
+
};
|
|
43
|
+
} catch (e) {
|
|
44
|
+
throw new Error("cannot retrieve configuration data for " + urlKey);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
150
47
|
}
|
|
151
48
|
|
|
152
49
|
export async function prepareRuntimeConfigurationUrls(
|
|
@@ -167,22 +64,32 @@ export async function prepareRuntimeConfigurationUrls(
|
|
|
167
64
|
const context = urlKeyToContext(layoutUrlKey);
|
|
168
65
|
|
|
169
66
|
try {
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return response.data;
|
|
174
|
-
});
|
|
175
|
-
|
|
67
|
+
const response = await axios.get(layoutUrl);
|
|
68
|
+
const { data } = response;
|
|
176
69
|
const layoutData = [{ [context]: data }];
|
|
177
70
|
const { id: layoutId } = data;
|
|
178
71
|
|
|
179
|
-
const preparedRuntimeConfigurationUrls =
|
|
180
|
-
runtimeConfigurationUrls,
|
|
181
|
-
isTablet
|
|
182
|
-
);
|
|
183
|
-
|
|
72
|
+
const preparedRuntimeConfigurationUrls = { ...runtimeConfigurationUrls };
|
|
184
73
|
delete preparedRuntimeConfigurationUrls[layoutUrlKey];
|
|
185
74
|
|
|
75
|
+
if (isTablet) {
|
|
76
|
+
preparedRuntimeConfigurationUrls[REMOTE_CONFIG_KEYS.TABLET.LAYOUT] &&
|
|
77
|
+
delete preparedRuntimeConfigurationUrls[
|
|
78
|
+
REMOTE_CONFIG_KEYS.MOBILE.LAYOUT
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
preparedRuntimeConfigurationUrls[REMOTE_CONFIG_KEYS.TABLET.CELL_STYLES] &&
|
|
82
|
+
delete preparedRuntimeConfigurationUrls[
|
|
83
|
+
REMOTE_CONFIG_KEYS.MOBILE.CELL_STYLES
|
|
84
|
+
];
|
|
85
|
+
} else {
|
|
86
|
+
delete preparedRuntimeConfigurationUrls[REMOTE_CONFIG_KEYS.TABLET.LAYOUT];
|
|
87
|
+
|
|
88
|
+
delete preparedRuntimeConfigurationUrls[
|
|
89
|
+
REMOTE_CONFIG_KEYS.TABLET.CELL_STYLES
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
|
|
186
93
|
if (cellStylesUrl && !cellStylesUrl.includes(layoutId)) {
|
|
187
94
|
const splitedUrl = cellStylesUrl.split("/");
|
|
188
95
|
const oldLayoutId = splitedUrl[splitedUrl.length - 2];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/quick-brick-core",
|
|
3
|
-
"version": "15.1.5-
|
|
3
|
+
"version": "15.1.5-rc.1",
|
|
4
4
|
"description": "Core package for Applicaster's Quick Brick App",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@applicaster/applicaster-types": "15.1.5-
|
|
32
|
-
"@applicaster/quick-brick-core-plugins": "15.1.5-
|
|
33
|
-
"@applicaster/zapp-pipes-v2-client": "15.1.5-
|
|
34
|
-
"@applicaster/zapp-react-native-bridge": "15.1.5-
|
|
35
|
-
"@applicaster/zapp-react-native-redux": "15.1.5-
|
|
36
|
-
"@applicaster/zapp-react-native-ui-components": "15.1.5-
|
|
37
|
-
"@applicaster/zapp-react-native-utils": "15.1.5-
|
|
31
|
+
"@applicaster/applicaster-types": "15.1.5-rc.1",
|
|
32
|
+
"@applicaster/quick-brick-core-plugins": "15.1.5-rc.1",
|
|
33
|
+
"@applicaster/zapp-pipes-v2-client": "15.1.5-rc.1",
|
|
34
|
+
"@applicaster/zapp-react-native-bridge": "15.1.5-rc.1",
|
|
35
|
+
"@applicaster/zapp-react-native-redux": "15.1.5-rc.1",
|
|
36
|
+
"@applicaster/zapp-react-native-ui-components": "15.1.5-rc.1",
|
|
37
|
+
"@applicaster/zapp-react-native-utils": "15.1.5-rc.1",
|
|
38
38
|
"atob": "^2.1.2",
|
|
39
39
|
"axios": "^0.28.0",
|
|
40
40
|
"btoa": "^1.2.1",
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Boot-time dedupe for remote JSON GETs.
|
|
3
|
-
* Shared across packages via globalThis so layout-manager + core
|
|
4
|
-
* don't double-fetch the same URL during startup.
|
|
5
|
-
*/
|
|
6
|
-
declare global {
|
|
7
|
-
// eslint-disable-next-line no-var
|
|
8
|
-
var __QB_REMOTE_JSON_INFLIGHT__: Map<string, Promise<unknown>> | undefined;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function cachedRemoteJson<T>(
|
|
12
|
-
url: string,
|
|
13
|
-
fetcher: () => Promise<T>
|
|
14
|
-
): Promise<T> {
|
|
15
|
-
if (!url) {
|
|
16
|
-
return fetcher();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (!globalThis.__QB_REMOTE_JSON_INFLIGHT__) {
|
|
20
|
-
globalThis.__QB_REMOTE_JSON_INFLIGHT__ = new Map();
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const cache = globalThis.__QB_REMOTE_JSON_INFLIGHT__;
|
|
24
|
-
|
|
25
|
-
if (!cache.has(url)) {
|
|
26
|
-
cache.set(
|
|
27
|
-
url,
|
|
28
|
-
fetcher().catch((error) => {
|
|
29
|
-
cache.delete(url);
|
|
30
|
-
|
|
31
|
-
throw error;
|
|
32
|
-
})
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return cache.get(url) as Promise<T>;
|
|
37
|
-
}
|