gemi 0.164.0 → 0.165.0
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/{chunk-1kt3p3dg.js → chunk-3q6adj7c.js} +10 -10
- package/dist/{chunk-1kt3p3dg.js.map → chunk-3q6adj7c.js.map} +3 -3
- package/dist/{chunk-dcnz24yt.js → chunk-7d0n00an.js} +1 -1
- package/dist/{chunk-34svz95a.js → chunk-bs0setym.js} +2 -2
- package/dist/{chunk-34svz95a.js.map → chunk-bs0setym.js.map} +1 -1
- package/dist/chunk-sk22zf9e.js +24 -0
- package/dist/{chunk-472qd3v9.js.map → chunk-sk22zf9e.js.map} +4 -4
- package/dist/{chunk-mvj8q5a7.js → chunk-w4227psm.js} +1 -1
- package/dist/chunks/{RealtimeClient-b6NvkUAQ.js → RealtimeClient-BX_HwEBK.js} +2 -2
- package/dist/chunks/{RealtimeClient-b6NvkUAQ.js.map → RealtimeClient-BX_HwEBK.js.map} +1 -1
- package/dist/chunks/{ThemeProvider-CkuoNG4Q.js → ThemeProvider-D4mhhONE.js} +78 -22
- package/dist/chunks/ThemeProvider-D4mhhONE.js.map +1 -0
- package/dist/chunks/{fetchFileRequest-DVWwtyWu.js → fetchFileRequest-C3wMigR3.js} +2 -2
- package/dist/chunks/{fetchFileRequest-DVWwtyWu.js.map → fetchFileRequest-C3wMigR3.js.map} +1 -1
- package/dist/chunks/{live-CpXfJmRN.js → live-CJOuf1Gu.js} +3 -3
- package/dist/chunks/{live-CpXfJmRN.js.map → live-CJOuf1Gu.js.map} +1 -1
- package/dist/chunks/{mutationExtras-BNFui6Pt.js → mutationExtras-DpB8MtNs.js} +2 -2
- package/dist/chunks/{mutationExtras-BNFui6Pt.js.map → mutationExtras-DpB8MtNs.js.map} +1 -1
- package/dist/client/ClientRouter.d.ts.map +1 -1
- package/dist/client/ClientRouterContext.d.ts.map +1 -1
- package/dist/client/ServerDataProvider.d.ts +6 -0
- package/dist/client/ServerDataProvider.d.ts.map +1 -1
- package/dist/client/chunkLoadRecovery.d.ts +56 -8
- package/dist/client/chunkLoadRecovery.d.ts.map +1 -1
- package/dist/client/helpers/loadRoutePayload.d.ts +8 -0
- package/dist/client/helpers/loadRoutePayload.d.ts.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +23 -9
- package/dist/client/index.js.map +1 -1
- package/dist/facades/index.js +1 -1
- package/dist/http/index.js +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/kernel/index.js +1 -1
- package/dist/server/httpProd.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/router/ViewRouteDispatcher.d.ts.map +1 -1
- package/dist/testing/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-472qd3v9.js +0 -24
- package/dist/chunks/ThemeProvider-CkuoNG4Q.js.map +0 -1
- /package/dist/{chunk-dcnz24yt.js.map → chunk-7d0n00an.js.map} +0 -0
- /package/dist/{chunk-mvj8q5a7.js.map → chunk-w4227psm.js.map} +0 -0
|
@@ -796,7 +796,7 @@ function loadedRealtimeClient() {
|
|
|
796
796
|
}
|
|
797
797
|
var loading = null;
|
|
798
798
|
/** The lazily loaded client. Replaceable in tests, to simulate a failed load. */
|
|
799
|
-
var lazyModules = { client: () => import("./RealtimeClient-
|
|
799
|
+
var lazyModules = { client: () => import("./RealtimeClient-BX_HwEBK.js") };
|
|
800
800
|
/**
|
|
801
801
|
* `./live`, loaded by the first live query. `<Page>` in `gemi/testing` sets
|
|
802
802
|
* `current` up front, so a live query on a provided socket subscribes during
|
|
@@ -804,7 +804,7 @@ var lazyModules = { client: () => import("./RealtimeClient-b6NvkUAQ.js") };
|
|
|
804
804
|
*/
|
|
805
805
|
var liveModule = {
|
|
806
806
|
current: null,
|
|
807
|
-
load: () => import("./live-
|
|
807
|
+
load: () => import("./live-CJOuf1Gu.js").then((n) => n.n)
|
|
808
808
|
};
|
|
809
809
|
/**
|
|
810
810
|
* The tab's client, loading its module and creating it on first use. `null`
|
|
@@ -2974,16 +2974,28 @@ function flattenComponentTree(componentTree) {
|
|
|
2974
2974
|
* (#548). The page cannot continue with the module it wanted, and a full load
|
|
2975
2975
|
* of the URL it was heading to gets it the current release's document.
|
|
2976
2976
|
*
|
|
2977
|
-
* One reload, guarded: a reload that lands on the same failure (a
|
|
2978
|
-
* genuinely missing, a proxy that keeps refusing it) must not
|
|
2979
|
-
* `sessionStorage` marker
|
|
2980
|
-
*
|
|
2977
|
+
* One reload per page, guarded: a reload that lands on the same failure (a
|
|
2978
|
+
* chunk that is genuinely missing, a proxy that keeps refusing it) must not
|
|
2979
|
+
* become a loop. A `sessionStorage` marker records when each URL was reloaded
|
|
2980
|
+
* onto and survives the reload it guards, so a second failure for the same URL
|
|
2981
|
+
* inside the cooldown is left to the route's error boundary. Per URL rather
|
|
2982
|
+
* than per tab (#1056): while two releases serve at once every navigation can
|
|
2983
|
+
* miss, and a tab-wide cooldown sent the second one to the error boundary.
|
|
2984
|
+
*
|
|
2985
|
+
* The same guard covers a navigation whose data came from another build
|
|
2986
|
+
* (`recoverFromBuildMismatch`).
|
|
2981
2987
|
*
|
|
2982
2988
|
* No DOM or React import at module scope: the server's reload stub
|
|
2983
2989
|
* (`server/staticAssetMiss.ts`) embeds the same guard as a script.
|
|
2984
2990
|
*/
|
|
2985
2991
|
/** The `sessionStorage` key the guard lives under, shared with the reload stub. */
|
|
2986
2992
|
var CHUNK_RELOAD_MARKER = "gemi:chunk-reload";
|
|
2993
|
+
/**
|
|
2994
|
+
* The response header carrying the client build id on a `.json` navigation
|
|
2995
|
+
* (#1056). The document carries its own as `buildId`; they differ when the
|
|
2996
|
+
* request reached a server running another release.
|
|
2997
|
+
*/
|
|
2998
|
+
var BUILD_HEADER = "x-gemi-build";
|
|
2987
2999
|
var enabled = true;
|
|
2988
3000
|
var options = {};
|
|
2989
3001
|
var reloading = false;
|
|
@@ -3036,20 +3048,55 @@ function recoverFromChunkLoadError(error, { source = "app", url } = {}) {
|
|
|
3036
3048
|
if (typeof window === "undefined" || !enabled || !isChunkLoadError(error)) return false;
|
|
3037
3049
|
if (reloading) return true;
|
|
3038
3050
|
const target = url ?? window.location.href;
|
|
3039
|
-
const blocked = reloadBlock(
|
|
3051
|
+
const blocked = reloadBlock(target);
|
|
3040
3052
|
if (options.onChunkLoadError?.({
|
|
3041
3053
|
error,
|
|
3042
3054
|
url: target,
|
|
3043
3055
|
source,
|
|
3044
3056
|
blocked
|
|
3045
3057
|
}) === false) return false;
|
|
3058
|
+
return loadInFull(target, blocked);
|
|
3059
|
+
}
|
|
3060
|
+
/**
|
|
3061
|
+
* Loads `url` in full because the navigation to it got its data from another
|
|
3062
|
+
* build (#1056): the views this page runs were not written for that data, and
|
|
3063
|
+
* rendering it anyway is how a deploy turned into "Something went wrong". The
|
|
3064
|
+
* full load gets a document and views of one build. Same guard as a chunk
|
|
3065
|
+
* failure, once per URL per cooldown; a navigation refused here renders the
|
|
3066
|
+
* data as before. Returns whether the page load was started.
|
|
3067
|
+
*/
|
|
3068
|
+
function recoverFromBuildMismatch({ url, clientBuild, serverBuild }) {
|
|
3069
|
+
if (typeof window === "undefined" || !enabled) return false;
|
|
3070
|
+
if (reloading) return true;
|
|
3071
|
+
const blocked = reloadBlock(url);
|
|
3072
|
+
if (options.onBuildMismatch?.({
|
|
3073
|
+
url,
|
|
3074
|
+
clientBuild,
|
|
3075
|
+
serverBuild,
|
|
3076
|
+
blocked
|
|
3077
|
+
}) === false) return false;
|
|
3078
|
+
return loadInFull(url, blocked);
|
|
3079
|
+
}
|
|
3080
|
+
/**
|
|
3081
|
+
* The build that answered a `.json` navigation, when it is not `clientBuild`;
|
|
3082
|
+
* otherwise `null`. Unknown on either side (dev, a test double, a server from
|
|
3083
|
+
* before the header) is not a mismatch.
|
|
3084
|
+
*/
|
|
3085
|
+
function otherBuild(response, clientBuild) {
|
|
3086
|
+
const served = response.headers?.get?.(BUILD_HEADER);
|
|
3087
|
+
return clientBuild && served && served !== clientBuild ? served : null;
|
|
3088
|
+
}
|
|
3089
|
+
function loadInFull(target, blocked) {
|
|
3046
3090
|
if (blocked !== null || !markReload(target)) return false;
|
|
3047
3091
|
reloading = true;
|
|
3048
3092
|
if (target === window.location.href) window.location.reload();
|
|
3049
3093
|
else window.location.assign(target);
|
|
3050
3094
|
return true;
|
|
3051
3095
|
}
|
|
3052
|
-
function
|
|
3096
|
+
function cooldownMs() {
|
|
3097
|
+
return options.cooldownMs ?? 3e4;
|
|
3098
|
+
}
|
|
3099
|
+
function reloadBlock(url) {
|
|
3053
3100
|
if (typeof navigator !== "undefined" && navigator.onLine === false) return "offline";
|
|
3054
3101
|
let raw;
|
|
3055
3102
|
try {
|
|
@@ -3057,27 +3104,36 @@ function reloadBlock(cooldownMs) {
|
|
|
3057
3104
|
} catch {
|
|
3058
3105
|
return "storage";
|
|
3059
3106
|
}
|
|
3060
|
-
const at = parseMarker(raw);
|
|
3061
|
-
return at !==
|
|
3107
|
+
const at = parseMarker(raw)[url];
|
|
3108
|
+
return at !== void 0 && withinCooldown(Date.now() - at, cooldownMs()) ? "cooldown" : null;
|
|
3062
3109
|
}
|
|
3063
3110
|
function withinCooldown(elapsed, cooldownMs) {
|
|
3064
3111
|
return elapsed >= 0 && elapsed < cooldownMs;
|
|
3065
3112
|
}
|
|
3113
|
+
/**
|
|
3114
|
+
* The marker: when each URL was last reloaded onto, `{ [url]: at }`. Anything
|
|
3115
|
+
* else in it (a marker written by an earlier gemi as `{ url, at }`) is ignored.
|
|
3116
|
+
*/
|
|
3066
3117
|
function parseMarker(raw) {
|
|
3067
|
-
|
|
3118
|
+
let parsed;
|
|
3068
3119
|
try {
|
|
3069
|
-
|
|
3070
|
-
return typeof at === "number" ? at : null;
|
|
3120
|
+
parsed = raw ? JSON.parse(raw) : null;
|
|
3071
3121
|
} catch {
|
|
3072
|
-
return
|
|
3122
|
+
return {};
|
|
3123
|
+
}
|
|
3124
|
+
const marker = {};
|
|
3125
|
+
if (parsed && typeof parsed === "object") {
|
|
3126
|
+
for (const [url, at] of Object.entries(parsed)) if (typeof at === "number") marker[url] = at;
|
|
3073
3127
|
}
|
|
3128
|
+
return marker;
|
|
3074
3129
|
}
|
|
3075
3130
|
function markReload(url) {
|
|
3076
3131
|
try {
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3132
|
+
const now = Date.now();
|
|
3133
|
+
const marker = {};
|
|
3134
|
+
for (const [other, at] of Object.entries(parseMarker(window.sessionStorage.getItem(CHUNK_RELOAD_MARKER)))) if (withinCooldown(now - at, cooldownMs())) marker[other] = at;
|
|
3135
|
+
marker[url] = now;
|
|
3136
|
+
window.sessionStorage.setItem(CHUNK_RELOAD_MARKER, JSON.stringify(marker));
|
|
3081
3137
|
return true;
|
|
3082
3138
|
} catch {
|
|
3083
3139
|
return false;
|
|
@@ -3221,7 +3277,7 @@ var ClientRouterProvider = (props) => {
|
|
|
3221
3277
|
return new Subject(false);
|
|
3222
3278
|
});
|
|
3223
3279
|
const i18nContext = useContext(I18nContext);
|
|
3224
|
-
const { staticRoutes, i18n } = useContext(ServerDataContext);
|
|
3280
|
+
const { staticRoutes, i18n, buildId } = useContext(ServerDataContext);
|
|
3225
3281
|
const localeRouted = i18n?.localeRouting !== "off";
|
|
3226
3282
|
const supportedLocales = localeRouted ? i18nContext.supportedLocales ?? NO_LOCALES : NO_LOCALES;
|
|
3227
3283
|
const locale = localeRouted ? i18nContext.locale : null;
|
|
@@ -3397,7 +3453,7 @@ var ClientRouterProvider = (props) => {
|
|
|
3397
3453
|
for (const view of routeManifest[routePath] ?? []) loadViewModule(view, "prefetch").catch(() => {});
|
|
3398
3454
|
await prefetchCache.prime(url, async () => {
|
|
3399
3455
|
const response = await fetch(url, { headers: { Purpose: "prefetch" } });
|
|
3400
|
-
if (!response.ok) return null;
|
|
3456
|
+
if (!response.ok || otherBuild(response, buildId)) return null;
|
|
3401
3457
|
return await readSettledRoutePayload(response);
|
|
3402
3458
|
});
|
|
3403
3459
|
};
|
|
@@ -3706,6 +3762,6 @@ function useTheme() {
|
|
|
3706
3762
|
return useContext(ThemeContext);
|
|
3707
3763
|
}
|
|
3708
3764
|
//#endregion
|
|
3709
|
-
export {
|
|
3765
|
+
export { USER_QUERY_CONFIG_KEYS as $, I18nContext as A, RealtimeContext as B, registerDictionary as C, useRoute as D, routeDataUrl as E, domainUrl as F, reconnectRealtime as G, followLive as H, isAbsoluteUrl as I, toVariantKey as J, loadLazy as K, ProgressManager as L, ServerDataContext as M, ServerDataProvider as N, useSearchParams as O, useLocation as P, QueryManagerProvider as Q, Action as R, loadDictionaryForRender as S, readRoutePayload as T, liveModule as U, configureRealtime as V, realtime as W, QueryConfigContext as X, applyParams as Y, QueryManagerContext as Z, isChunkLoadError as _, useRouteTransition as a, retryDelayFor as at, recoverFromChunkLoadError as b, ClientRouterContext as c, Subject as ct, ComponentsProvider as d, pickDefined as et, initialViewModulesReady as f, configureChunkLoadRecovery as g, CHUNK_RELOAD_MARKER as h, RouteTransitionProvider as i, parseRetryAfter as it, I18nProvider as j, useNavigate as k, ClientRouterProvider as l, subscribeViewModules as m, useTheme as n, readResponseBody as nt, useChannelSubscription as o, shouldRetryQuery as ot, loadViewModule as p, loadedModule as q, m as r, isRetryableQueryError as rt, useCoalesced as s, QueryError as st, ThemeProvider as t, DEFAULT_STALE_TIME as tt, ComponentsContext as u, otherBuild as v, setActiveLocale as w, loadDictionary as x, recoverFromBuildMismatch as y, createMemoryHistory as z };
|
|
3710
3766
|
|
|
3711
|
-
//# sourceMappingURL=ThemeProvider-
|
|
3767
|
+
//# sourceMappingURL=ThemeProvider-D4mhhONE.js.map
|