gemi 0.192.0 → 0.193.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/dist/{chunk-qg60pgve.js → chunk-fhvyq67n.js} +1 -1
- package/dist/{chunk-qnc840pb.js → chunk-gsrf5c3c.js} +2 -2
- package/dist/{chunk-qnc840pb.js.map → chunk-gsrf5c3c.js.map} +1 -1
- package/dist/chunk-vese6sny.js +24 -0
- package/dist/{chunk-mx9zcq7w.js.map → chunk-vese6sny.js.map} +3 -3
- package/dist/chunks/{RealtimeClient-CyGWZr6p.js → RealtimeClient-BVQeh_yg.js} +2 -2
- package/dist/chunks/{RealtimeClient-CyGWZr6p.js.map → RealtimeClient-BVQeh_yg.js.map} +1 -1
- package/dist/chunks/{ThemeProvider-BnmnRvEc.js → ThemeProvider-G2g5Z1ZS.js} +142 -30
- package/dist/chunks/{ThemeProvider-BnmnRvEc.js.map → ThemeProvider-G2g5Z1ZS.js.map} +1 -1
- package/dist/chunks/{fetchFileRequest-D4fAcY7D.js → fetchFileRequest-Bzva9J59.js} +2 -2
- package/dist/chunks/{fetchFileRequest-D4fAcY7D.js.map → fetchFileRequest-Bzva9J59.js.map} +1 -1
- package/dist/chunks/{live-B4RW02g2.js → live-C2Sck5PO.js} +3 -3
- package/dist/chunks/{live-B4RW02g2.js.map → live-C2Sck5PO.js.map} +1 -1
- package/dist/chunks/{mutationExtras-DgdYjcaa.js → mutationExtras-HC7AC6zn.js} +2 -2
- package/dist/chunks/{mutationExtras-DgdYjcaa.js.map → mutationExtras-HC7AC6zn.js.map} +1 -1
- package/dist/chunks/{subscriptionStream-Ca5V54ee.js → subscriptionStream-CaTWWJwt.js} +2 -2
- package/dist/chunks/{subscriptionStream-Ca5V54ee.js.map → subscriptionStream-CaTWWJwt.js.map} +1 -1
- package/dist/client/chunkLoadRecovery.d.ts +42 -5
- package/dist/client/chunkLoadRecovery.d.ts.map +1 -1
- package/dist/client/index.js +4 -4
- package/dist/server/index.js +1 -1
- package/dist/testing/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-mx9zcq7w.js +0 -24
- /package/dist/{chunk-qg60pgve.js.map → chunk-fhvyq67n.js.map} +0 -0
|
@@ -1053,7 +1053,7 @@ function loadedRealtimeClient() {
|
|
|
1053
1053
|
}
|
|
1054
1054
|
var loading = null;
|
|
1055
1055
|
/** The lazily loaded client. Replaceable in tests, to simulate a failed load. */
|
|
1056
|
-
var lazyModules = { client: () => import("./RealtimeClient-
|
|
1056
|
+
var lazyModules = { client: () => import("./RealtimeClient-BVQeh_yg.js") };
|
|
1057
1057
|
/**
|
|
1058
1058
|
* `./live`, loaded by the first live query. `<Page>` in `gemi/testing` sets
|
|
1059
1059
|
* `current` up front, so a live query on a provided socket subscribes during
|
|
@@ -1061,7 +1061,7 @@ var lazyModules = { client: () => import("./RealtimeClient-CyGWZr6p.js") };
|
|
|
1061
1061
|
*/
|
|
1062
1062
|
var liveModule = {
|
|
1063
1063
|
current: null,
|
|
1064
|
-
load: () => import("./live-
|
|
1064
|
+
load: () => import("./live-C2Sck5PO.js").then((n) => n.n)
|
|
1065
1065
|
};
|
|
1066
1066
|
/**
|
|
1067
1067
|
* The tab's client, loading its module and creating it on first use. `null`
|
|
@@ -3244,6 +3244,8 @@ function flattenComponentTree(componentTree) {
|
|
|
3244
3244
|
* inside the cooldown is left to the route's error boundary. Per URL rather
|
|
3245
3245
|
* than per tab (#1056): while two releases serve at once every navigation can
|
|
3246
3246
|
* miss, and a tab-wide cooldown sent the second one to the error boundary.
|
|
3247
|
+
* Where `sessionStorage` cannot be used, the marker lives in `window.name`
|
|
3248
|
+
* instead (#1186); see `chunkReloadGuard`.
|
|
3247
3249
|
*
|
|
3248
3250
|
* The same guard covers a navigation whose data came from another build
|
|
3249
3251
|
* (`recoverFromBuildMismatch`).
|
|
@@ -3283,6 +3285,7 @@ var pendingLoad = null;
|
|
|
3283
3285
|
function configureChunkLoadRecovery(next) {
|
|
3284
3286
|
enabled = next !== false;
|
|
3285
3287
|
options = next || {};
|
|
3288
|
+
tidyWindowName();
|
|
3286
3289
|
}
|
|
3287
3290
|
/**
|
|
3288
3291
|
* The router calls this as each client-side navigation starts. A full load
|
|
@@ -3389,46 +3392,155 @@ function cooldownMs() {
|
|
|
3389
3392
|
}
|
|
3390
3393
|
function reloadBlock(url) {
|
|
3391
3394
|
if (typeof navigator !== "undefined" && navigator.onLine === false) return "offline";
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
raw = window.sessionStorage.getItem(CHUNK_RELOAD_MARKER);
|
|
3395
|
-
} catch {
|
|
3396
|
-
return "storage";
|
|
3397
|
-
}
|
|
3398
|
-
const at = parseMarker(raw)[url];
|
|
3399
|
-
return at !== void 0 && withinCooldown(Date.now() - at, cooldownMs()) ? "cooldown" : null;
|
|
3395
|
+
const verdict = chunkReloadGuard(CHUNK_RELOAD_MARKER, url, cooldownMs(), false);
|
|
3396
|
+
return verdict === "ok" ? null : verdict;
|
|
3400
3397
|
}
|
|
3401
3398
|
function withinCooldown(elapsed, cooldownMs) {
|
|
3402
3399
|
return elapsed >= 0 && elapsed < cooldownMs;
|
|
3403
3400
|
}
|
|
3401
|
+
function markReload(url) {
|
|
3402
|
+
if (chunkReloadGuard("gemi:chunk-reload", url, cooldownMs(), true) !== "ok") return false;
|
|
3403
|
+
tidyWindowName();
|
|
3404
|
+
return true;
|
|
3405
|
+
}
|
|
3406
|
+
var tidyTimer;
|
|
3404
3407
|
/**
|
|
3405
|
-
*
|
|
3406
|
-
*
|
|
3408
|
+
* Takes gemi's marker out of `window.name` (back to `""`) once it guards
|
|
3409
|
+
* nothing (#1188): the page may want the name for itself, under the same
|
|
3410
|
+
* "only while it is empty" rule gemi follows. Now when nothing in it is live,
|
|
3411
|
+
* otherwise once the newest entry's cooldown has passed, checked again then
|
|
3412
|
+
* since a reload may have been recorded in the meantime. Only a name that
|
|
3413
|
+
* holds gemi's marker is ever cleared; see `chunkReloadGuard`'s `"tidy"`.
|
|
3407
3414
|
*/
|
|
3408
|
-
function
|
|
3409
|
-
|
|
3415
|
+
function tidyWindowName() {
|
|
3416
|
+
clearTimeout(tidyTimer);
|
|
3417
|
+
tidyTimer = void 0;
|
|
3418
|
+
if (typeof window === "undefined") return;
|
|
3419
|
+
let delay;
|
|
3410
3420
|
try {
|
|
3411
|
-
|
|
3421
|
+
if (chunkReloadGuard("gemi:chunk-reload", window.location.href, cooldownMs(), "tidy") !== "cooldown") return;
|
|
3422
|
+
const held = JSON.parse(window.name.slice(18));
|
|
3423
|
+
const now = Date.now();
|
|
3424
|
+
delay = Math.max(...Object.values(held.m).filter((at) => typeof at === "number" && at <= now)) + cooldownMs() - now;
|
|
3412
3425
|
} catch {
|
|
3413
|
-
return
|
|
3414
|
-
}
|
|
3415
|
-
const marker = {};
|
|
3416
|
-
if (parsed && typeof parsed === "object") {
|
|
3417
|
-
for (const [url, at] of Object.entries(parsed)) if (typeof at === "number") marker[url] = at;
|
|
3426
|
+
return;
|
|
3418
3427
|
}
|
|
3419
|
-
return
|
|
3428
|
+
if (!Number.isFinite(delay)) return;
|
|
3429
|
+
tidyTimer = setTimeout(tidyWindowName, Math.max(0, delay) + 1);
|
|
3420
3430
|
}
|
|
3421
|
-
|
|
3431
|
+
/**
|
|
3432
|
+
* The cross-document guard, shared by the client and the server's reload stub
|
|
3433
|
+
* (which embeds this function's source, so it uses nothing but globals and its
|
|
3434
|
+
* arguments). With `claim` false it only reads: `"cooldown"` when a reload
|
|
3435
|
+
* onto `url` was recorded inside `cooldownMs`, `"storage"` when no marker can
|
|
3436
|
+
* be read at all, otherwise `"ok"`. With `claim` true it also records the
|
|
3437
|
+
* reload, and answers `"ok"` only once the record was written and read back
|
|
3438
|
+
* unchanged; a caller navigates on nothing less. With `"tidy"` it only looks
|
|
3439
|
+
* at `window.name`: a gemi marker with no live entry for this origin (expired,
|
|
3440
|
+
* from the future, another origin's, or one that does not parse) is cleared
|
|
3441
|
+
* to `""` and `"ok"` answered; `"cooldown"` while an entry is still live.
|
|
3442
|
+
*
|
|
3443
|
+
* Two places can hold the marker:
|
|
3444
|
+
*
|
|
3445
|
+
* - `sessionStorage[key]`: `{ [url]: at }`, the format earlier releases read
|
|
3446
|
+
* and write, so a page from one and a stub from another share the guard.
|
|
3447
|
+
* - `window.name`, when `sessionStorage` throws or will not take the write
|
|
3448
|
+
* (#1186). It survives a load in the same tab, but it is shared state: the
|
|
3449
|
+
* page may use it, and another origin the tab goes to can read it. So it is
|
|
3450
|
+
* used only while it is empty or already holds gemi's marker — a value of
|
|
3451
|
+
* anyone else's is left exactly as it is, and the guard then fails closed —
|
|
3452
|
+
* and it holds no URL: `key + ":" + { o: hash(origin), m: { [hash(origin +
|
|
3453
|
+
* pathname)]: at } }`. A marker written by another origin (`o` differs) or
|
|
3454
|
+
* one that does not parse holds no reloads and is replaced on the next
|
|
3455
|
+
* write. Two paths whose hashes collide share one cooldown, which only ever
|
|
3456
|
+
* refuses a reload.
|
|
3457
|
+
*
|
|
3458
|
+
* A reload recorded in either place counts. Entries past the cooldown — and
|
|
3459
|
+
* from the future, after the clock was set back — are dropped as a new one is
|
|
3460
|
+
* written, so the marker holds only the reloads it still guards.
|
|
3461
|
+
*/
|
|
3462
|
+
function chunkReloadGuard(key, url, cooldownMs, claim) {
|
|
3463
|
+
const now = Date.now();
|
|
3464
|
+
const fresh = function(at) {
|
|
3465
|
+
return typeof at === "number" && now - at >= 0 && now - at < cooldownMs;
|
|
3466
|
+
};
|
|
3467
|
+
const parse = function(raw) {
|
|
3468
|
+
try {
|
|
3469
|
+
const value = raw ? JSON.parse(raw) : null;
|
|
3470
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
3471
|
+
} catch {
|
|
3472
|
+
return {};
|
|
3473
|
+
}
|
|
3474
|
+
};
|
|
3475
|
+
const live = function(marker) {
|
|
3476
|
+
const kept = {};
|
|
3477
|
+
for (const k in marker) if (fresh(marker[k])) kept[k] = marker[k];
|
|
3478
|
+
return kept;
|
|
3479
|
+
};
|
|
3480
|
+
const hash = function(text) {
|
|
3481
|
+
let h = 2166136261;
|
|
3482
|
+
for (let i = 0; i < text.length; i++) h = Math.imul(h ^ text.charCodeAt(i), 16777619);
|
|
3483
|
+
return (h >>> 0).toString(36);
|
|
3484
|
+
};
|
|
3485
|
+
let storage = null;
|
|
3486
|
+
let stored = {};
|
|
3422
3487
|
try {
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
for (const [other, at] of Object.entries(parseMarker(window.sessionStorage.getItem(CHUNK_RELOAD_MARKER)))) if (withinCooldown(now - at, cooldownMs())) marker[other] = at;
|
|
3426
|
-
marker[url] = now;
|
|
3427
|
-
window.sessionStorage.setItem(CHUNK_RELOAD_MARKER, JSON.stringify(marker));
|
|
3428
|
-
return true;
|
|
3488
|
+
storage = window.sessionStorage;
|
|
3489
|
+
stored = parse(storage.getItem(key));
|
|
3429
3490
|
} catch {
|
|
3430
|
-
|
|
3491
|
+
storage = null;
|
|
3431
3492
|
}
|
|
3493
|
+
const prefix = key + ":";
|
|
3494
|
+
let origin = "";
|
|
3495
|
+
let page = "";
|
|
3496
|
+
try {
|
|
3497
|
+
const target = new URL(url, window.location.href);
|
|
3498
|
+
origin = hash(new URL(window.location.href).origin);
|
|
3499
|
+
page = hash(target.origin + target.pathname);
|
|
3500
|
+
} catch {}
|
|
3501
|
+
let named = null;
|
|
3502
|
+
try {
|
|
3503
|
+
const name = window.name;
|
|
3504
|
+
if (!page) named = null;
|
|
3505
|
+
else if (name === "") named = {};
|
|
3506
|
+
else if (name.indexOf(prefix) === 0) {
|
|
3507
|
+
const held = parse(name.slice(prefix.length));
|
|
3508
|
+
const entries = held.m;
|
|
3509
|
+
named = held.o === origin && entries && typeof entries === "object" && !Array.isArray(entries) ? entries : {};
|
|
3510
|
+
}
|
|
3511
|
+
} catch {
|
|
3512
|
+
named = null;
|
|
3513
|
+
}
|
|
3514
|
+
if (claim === "tidy") {
|
|
3515
|
+
try {
|
|
3516
|
+
const current = window.name;
|
|
3517
|
+
if (named === null || current.indexOf(prefix) !== 0) return "ok";
|
|
3518
|
+
for (const k in named) if (fresh(named[k])) return "cooldown";
|
|
3519
|
+
window.name = "";
|
|
3520
|
+
} catch {}
|
|
3521
|
+
return "ok";
|
|
3522
|
+
}
|
|
3523
|
+
if (fresh(stored[url]) || named && fresh(named[page])) return "cooldown";
|
|
3524
|
+
if (!storage && !named) return "storage";
|
|
3525
|
+
if (!claim) return "ok";
|
|
3526
|
+
if (storage) try {
|
|
3527
|
+
const nextStored = live(stored);
|
|
3528
|
+
nextStored[url] = now;
|
|
3529
|
+
const serialised = JSON.stringify(nextStored);
|
|
3530
|
+
storage.setItem(key, serialised);
|
|
3531
|
+
if (storage.getItem(key) === serialised) return "ok";
|
|
3532
|
+
} catch {}
|
|
3533
|
+
if (named) try {
|
|
3534
|
+
const nextNamed = live(named);
|
|
3535
|
+
nextNamed[page] = now;
|
|
3536
|
+
const value = prefix + JSON.stringify({
|
|
3537
|
+
o: origin,
|
|
3538
|
+
m: nextNamed
|
|
3539
|
+
});
|
|
3540
|
+
window.name = value;
|
|
3541
|
+
if (window.name === value) return "ok";
|
|
3542
|
+
} catch {}
|
|
3543
|
+
return "storage";
|
|
3432
3544
|
}
|
|
3433
3545
|
//#endregion
|
|
3434
3546
|
//#region client/ComponentContext.tsx
|
|
@@ -4055,4 +4167,4 @@ function useTheme() {
|
|
|
4055
4167
|
//#endregion
|
|
4056
4168
|
export { QueryManagerProvider as $, useNavigate as A, createMemoryHistory as B, loadDictionaryForRender as C, routeDataUrl as D, readRoutePayload as E, useLocation as F, realtime as G, configureRealtime as H, domainUrl as I, loadedModule as J, reconnectRealtime as K, isAbsoluteUrl as L, I18nProvider as M, ServerDataContext as N, useRoute as O, ServerDataProvider as P, QueryManagerContext as Q, ProgressManager as R, loadDictionary as S, setActiveLocale as T, followLive as U, RealtimeContext as V, liveModule as W, applyParams as X, toVariantKey as Y, QueryConfigContext as Z, isChunkLoadError as _, Subject as _t, useRouteTransition as a, resetAuthenticationIncident as at, recoverFromBuildMismatch as b, ClientRouterContext as c, isExternalRedirect as ct, ComponentsProvider as d, equalJitter as dt, USER_QUERY_CONFIG_KEYS as et, initialViewModulesReady as f, isRetryableQueryError as ft, configureChunkLoadRecovery as g, QueryError as gt, CHUNK_RELOAD_MARKER as h, shouldRetryQuery as ht, RouteTransitionProvider as i, reportAuthenticationRefusal as it, I18nContext as j, useSearchParams as k, ClientRouterProvider as l, safeRedirectPath as lt, subscribeViewModules as m, retryDelayFor as mt, useTheme as n, DEFAULT_STALE_TIME as nt, useChannelSubscription as o, setAuthenticationNavigator as ot, loadViewModule as p, parseRetryAfter as pt, loadLazy as q, m as r, configureAuthenticationErrors as rt, useCoalesced as s, INTENDED_URL_PARAM as st, ThemeProvider as t, pickDefined as tt, ComponentsContext as u, readResponseBody as ut, navigationStarted as v, registerDictionary as w, recoverFromChunkLoadError as x, otherBuild as y, Action as z };
|
|
4057
4169
|
|
|
4058
|
-
//# sourceMappingURL=ThemeProvider-
|
|
4170
|
+
//# sourceMappingURL=ThemeProvider-G2g5Z1ZS.js.map
|