@calimero-network/mero-react 5.1.0 → 6.0.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/index.cjs +81 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -6
- package/dist/index.d.ts +77 -6
- package/dist/index.js +79 -17
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -328,6 +328,7 @@ function MeroProvider({
|
|
|
328
328
|
const [contextId, setContextIdState] = react.useState(() => getContextId());
|
|
329
329
|
const [contextIdentity, setContextIdentityState] = react.useState(() => getContextIdentity());
|
|
330
330
|
const meroRef = react.useRef(null);
|
|
331
|
+
const recoveringRef = react.useRef(false);
|
|
331
332
|
const callbackRef = react.useRef(void 0);
|
|
332
333
|
if (callbackRef.current === void 0 && isBrowser) {
|
|
333
334
|
callbackRef.current = meroJs.parseAuthCallback(window.location.href);
|
|
@@ -351,12 +352,18 @@ function MeroProvider({
|
|
|
351
352
|
async (instance) => {
|
|
352
353
|
const accessToken = tokenStore.getTokens()?.access_token;
|
|
353
354
|
if (!accessToken) return false;
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
355
|
+
const validate = async (token) => {
|
|
356
|
+
try {
|
|
357
|
+
const { valid } = await instance.auth.validateToken(token);
|
|
358
|
+
return valid;
|
|
359
|
+
} catch {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
if (await validate(accessToken)) return true;
|
|
364
|
+
const rotated = tokenStore.getTokens()?.access_token;
|
|
365
|
+
if (!rotated || rotated === accessToken) return false;
|
|
366
|
+
return validate(rotated);
|
|
360
367
|
},
|
|
361
368
|
[tokenStore]
|
|
362
369
|
);
|
|
@@ -483,9 +490,23 @@ function MeroProvider({
|
|
|
483
490
|
const onError = (err) => {
|
|
484
491
|
if (!active) return;
|
|
485
492
|
setIsOnline(false);
|
|
486
|
-
if (err.message.includes("401"))
|
|
487
|
-
|
|
488
|
-
|
|
493
|
+
if (!err.message.includes("401")) return;
|
|
494
|
+
if (recoveringRef.current) return;
|
|
495
|
+
recoveringRef.current = true;
|
|
496
|
+
void (async () => {
|
|
497
|
+
try {
|
|
498
|
+
const instance = meroRef.current;
|
|
499
|
+
if (!instance) return;
|
|
500
|
+
if (await checkAuth(instance)) {
|
|
501
|
+
if (active) await instance.events.connect().catch(() => {
|
|
502
|
+
});
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
if (active) logout();
|
|
506
|
+
} finally {
|
|
507
|
+
recoveringRef.current = false;
|
|
508
|
+
}
|
|
509
|
+
})();
|
|
489
510
|
};
|
|
490
511
|
sse.on("connect", onConnect);
|
|
491
512
|
sse.on("error", onError);
|
|
@@ -497,7 +518,7 @@ function MeroProvider({
|
|
|
497
518
|
sse.off("connect", onConnect);
|
|
498
519
|
sse.off("error", onError);
|
|
499
520
|
};
|
|
500
|
-
}, [isAuthenticated, mero]);
|
|
521
|
+
}, [isAuthenticated, mero, checkAuth, logout]);
|
|
501
522
|
const contextValue = react.useMemo(
|
|
502
523
|
() => ({
|
|
503
524
|
mero,
|
|
@@ -1990,6 +2011,15 @@ function useNamespace(namespaceId) {
|
|
|
1990
2011
|
);
|
|
1991
2012
|
return { namespace: data, loading, error, refetch };
|
|
1992
2013
|
}
|
|
2014
|
+
function useNodeIdentity() {
|
|
2015
|
+
const { mero } = useMero();
|
|
2016
|
+
const { data, loading, error, refetch } = useAsyncResource(
|
|
2017
|
+
mero ? () => mero.admin.getNodeIdentity() : null,
|
|
2018
|
+
null,
|
|
2019
|
+
[mero]
|
|
2020
|
+
);
|
|
2021
|
+
return { identity: data, loading, error, refetch };
|
|
2022
|
+
}
|
|
1993
2023
|
function useNamespaceIdentity(namespaceId) {
|
|
1994
2024
|
const { mero } = useMero();
|
|
1995
2025
|
const { data, loading, error, refetch } = useAsyncResource(
|
|
@@ -2359,6 +2389,35 @@ function useDetachContextFromGroup() {
|
|
|
2359
2389
|
);
|
|
2360
2390
|
return { detachContextFromGroup, loading, error };
|
|
2361
2391
|
}
|
|
2392
|
+
var DEFAULT_MIGRATION_POLL_INTERVAL_MS = 5e3;
|
|
2393
|
+
function useMigrationEvents(namespaceId, onEvent) {
|
|
2394
|
+
const { mero } = useMero();
|
|
2395
|
+
const mountedRef = useMountedRef();
|
|
2396
|
+
const [live, setLive] = react.useState(false);
|
|
2397
|
+
const handlerRef = react.useRef(onEvent);
|
|
2398
|
+
handlerRef.current = onEvent;
|
|
2399
|
+
react.useEffect(() => {
|
|
2400
|
+
if (!mero || !namespaceId) return;
|
|
2401
|
+
const sse = mero.events;
|
|
2402
|
+
const unsubscribe = sse.onMigrationEvent((event) => handlerRef.current(event));
|
|
2403
|
+
let cancelled = false;
|
|
2404
|
+
void (async () => {
|
|
2405
|
+
try {
|
|
2406
|
+
await sse.connect();
|
|
2407
|
+
await sse.subscribe({ groupIds: [namespaceId] });
|
|
2408
|
+
if (!cancelled && mountedRef.current) setLive(true);
|
|
2409
|
+
} catch {
|
|
2410
|
+
if (!cancelled && mountedRef.current) setLive(false);
|
|
2411
|
+
}
|
|
2412
|
+
})();
|
|
2413
|
+
return () => {
|
|
2414
|
+
cancelled = true;
|
|
2415
|
+
if (mountedRef.current) setLive(false);
|
|
2416
|
+
unsubscribe();
|
|
2417
|
+
};
|
|
2418
|
+
}, [mero, namespaceId, mountedRef]);
|
|
2419
|
+
return live;
|
|
2420
|
+
}
|
|
2362
2421
|
function useMigrationStatus(namespaceId, options) {
|
|
2363
2422
|
const { mero } = useMero();
|
|
2364
2423
|
const [status, setStatus] = react.useState(null);
|
|
@@ -2403,7 +2462,8 @@ function useMigrationStatus(namespaceId, options) {
|
|
|
2403
2462
|
react.useEffect(() => {
|
|
2404
2463
|
void refetch();
|
|
2405
2464
|
}, [refetch]);
|
|
2406
|
-
const
|
|
2465
|
+
const sseLive = useMigrationEvents(namespaceId, () => void refetch());
|
|
2466
|
+
const pollIntervalMs = options?.pollIntervalMs ?? (sseLive ? void 0 : DEFAULT_MIGRATION_POLL_INTERVAL_MS);
|
|
2407
2467
|
react.useEffect(() => {
|
|
2408
2468
|
if (!pollIntervalMs || !mero || !namespaceId) return;
|
|
2409
2469
|
const handle = setInterval(() => void refetch(), pollIntervalMs);
|
|
@@ -2416,6 +2476,12 @@ function useMigrationStatus(namespaceId, options) {
|
|
|
2416
2476
|
rollup,
|
|
2417
2477
|
members,
|
|
2418
2478
|
allMigrated: rollup?.allMigrated ?? false,
|
|
2479
|
+
/**
|
|
2480
|
+
* When this node watched the fleet converge, or `null`. Durable, unlike
|
|
2481
|
+
* `allMigrated`, which is recomputed from in-TTL heartbeats and lapses back
|
|
2482
|
+
* to false when a member simply goes quiet.
|
|
2483
|
+
*/
|
|
2484
|
+
fleetCompletedAt: status?.fleetCompletedAt ?? null,
|
|
2419
2485
|
membersPendingSignature: rollup?.membersPendingSignature ?? 0,
|
|
2420
2486
|
/** Members whose migrate aborted (migration-check failed or apply errored). */
|
|
2421
2487
|
failed: rollup?.failed ?? 0,
|
|
@@ -2535,7 +2601,6 @@ var EMPTY_GROUP_APP_VERSION = {
|
|
|
2535
2601
|
version: null,
|
|
2536
2602
|
applicationId: null,
|
|
2537
2603
|
pendingApply: false,
|
|
2538
|
-
upgradePolicy: null,
|
|
2539
2604
|
activeUpgrade: null
|
|
2540
2605
|
};
|
|
2541
2606
|
function isZeroAppKey(appKey) {
|
|
@@ -2567,17 +2632,14 @@ function useGroupAppVersion(groupId) {
|
|
|
2567
2632
|
const namespace = namespaces.find((entry) => entry.namespaceId === groupId);
|
|
2568
2633
|
let appKey;
|
|
2569
2634
|
let applicationId;
|
|
2570
|
-
let upgradePolicy;
|
|
2571
2635
|
let activeUpgrade = null;
|
|
2572
2636
|
if (namespace) {
|
|
2573
2637
|
appKey = namespace.appKey;
|
|
2574
2638
|
applicationId = namespace.targetApplicationId;
|
|
2575
|
-
upgradePolicy = namespace.upgradePolicy ?? null;
|
|
2576
2639
|
} else {
|
|
2577
2640
|
const info = await mero.admin.getGroupInfo(groupId);
|
|
2578
2641
|
appKey = info.appKey;
|
|
2579
2642
|
applicationId = info.targetApplicationId;
|
|
2580
|
-
upgradePolicy = info.upgradePolicy ?? null;
|
|
2581
2643
|
activeUpgrade = info.activeUpgrade ?? null;
|
|
2582
2644
|
}
|
|
2583
2645
|
let version = null;
|
|
@@ -2591,7 +2653,7 @@ function useGroupAppVersion(groupId) {
|
|
|
2591
2653
|
}
|
|
2592
2654
|
}
|
|
2593
2655
|
if (mountedRef.current && seq === reqRef.current) {
|
|
2594
|
-
setData({ version, applicationId, pendingApply,
|
|
2656
|
+
setData({ version, applicationId, pendingApply, activeUpgrade });
|
|
2595
2657
|
}
|
|
2596
2658
|
} catch (err) {
|
|
2597
2659
|
const errorValue = toError(err);
|
|
@@ -2802,6 +2864,7 @@ exports.AppMode = AppMode;
|
|
|
2802
2864
|
exports.CalimeroLogo = CalimeroLogo;
|
|
2803
2865
|
exports.ConnectButton = ConnectButton;
|
|
2804
2866
|
exports.ConnectionType = ConnectionType;
|
|
2867
|
+
exports.DEFAULT_MIGRATION_POLL_INTERVAL_MS = DEFAULT_MIGRATION_POLL_INTERVAL_MS;
|
|
2805
2868
|
exports.LoginModal = LoginModal;
|
|
2806
2869
|
exports.MERO_CSS_VARS = MERO_CSS_VARS;
|
|
2807
2870
|
exports.MeroContext = MeroContext;
|
|
@@ -2862,6 +2925,7 @@ exports.useJoinSubgroupInheritance = useJoinSubgroupInheritance;
|
|
|
2862
2925
|
exports.useLatestVersion = useLatestVersion;
|
|
2863
2926
|
exports.useMemberMetadata = useMemberMetadata;
|
|
2864
2927
|
exports.useMero = useMero;
|
|
2928
|
+
exports.useMigrationEvents = useMigrationEvents;
|
|
2865
2929
|
exports.useMigrationStatus = useMigrationStatus;
|
|
2866
2930
|
exports.useMyAuthoredMigration = useMyAuthoredMigration;
|
|
2867
2931
|
exports.useNamespace = useNamespace;
|
|
@@ -2869,6 +2933,7 @@ exports.useNamespaceGroups = useNamespaceGroups;
|
|
|
2869
2933
|
exports.useNamespaceIdentity = useNamespaceIdentity;
|
|
2870
2934
|
exports.useNamespaces = useNamespaces;
|
|
2871
2935
|
exports.useNamespacesForApplication = useNamespacesForApplication;
|
|
2936
|
+
exports.useNodeIdentity = useNodeIdentity;
|
|
2872
2937
|
exports.useRemoveGroupMembers = useRemoveGroupMembers;
|
|
2873
2938
|
exports.useReparentGroup = useReparentGroup;
|
|
2874
2939
|
exports.useResyncContext = useResyncContext;
|