@calimero-network/mero-react 2.4.0 → 2.6.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/index.cjs +313 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +99 -3
- package/dist/index.d.ts +99 -3
- package/dist/index.js +309 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -2294,6 +2294,313 @@ function useDetachContextFromGroup() {
|
|
|
2294
2294
|
);
|
|
2295
2295
|
return { detachContextFromGroup, loading, error };
|
|
2296
2296
|
}
|
|
2297
|
+
function useMigrationStatus(namespaceId, options) {
|
|
2298
|
+
const { mero } = useMero();
|
|
2299
|
+
const [status, setStatus] = react.useState(null);
|
|
2300
|
+
const [loading, setLoading] = react.useState(false);
|
|
2301
|
+
const [error, setError] = react.useState(null);
|
|
2302
|
+
const mountedRef = useMountedRef();
|
|
2303
|
+
const reqRef = react.useRef(0);
|
|
2304
|
+
const refetch = react.useCallback(async () => {
|
|
2305
|
+
if (!mero || !namespaceId) {
|
|
2306
|
+
if (mountedRef.current) {
|
|
2307
|
+
setStatus(null);
|
|
2308
|
+
setError(null);
|
|
2309
|
+
setLoading(false);
|
|
2310
|
+
}
|
|
2311
|
+
return;
|
|
2312
|
+
}
|
|
2313
|
+
const seq = ++reqRef.current;
|
|
2314
|
+
if (mountedRef.current) {
|
|
2315
|
+
setLoading(true);
|
|
2316
|
+
setError(null);
|
|
2317
|
+
}
|
|
2318
|
+
try {
|
|
2319
|
+
const result = await mero.admin.getMigrationStatus(namespaceId);
|
|
2320
|
+
if (mountedRef.current && seq === reqRef.current) {
|
|
2321
|
+
setStatus(result);
|
|
2322
|
+
}
|
|
2323
|
+
} catch (err) {
|
|
2324
|
+
const errorValue = toError(err);
|
|
2325
|
+
if (mountedRef.current && seq === reqRef.current) {
|
|
2326
|
+
setError(errorValue);
|
|
2327
|
+
}
|
|
2328
|
+
} finally {
|
|
2329
|
+
if (mountedRef.current && seq === reqRef.current) {
|
|
2330
|
+
setLoading(false);
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
}, [namespaceId, mero, mountedRef]);
|
|
2334
|
+
react.useEffect(() => {
|
|
2335
|
+
setStatus(null);
|
|
2336
|
+
setError(null);
|
|
2337
|
+
}, [namespaceId]);
|
|
2338
|
+
react.useEffect(() => {
|
|
2339
|
+
void refetch();
|
|
2340
|
+
}, [refetch]);
|
|
2341
|
+
const pollIntervalMs = options?.pollIntervalMs;
|
|
2342
|
+
react.useEffect(() => {
|
|
2343
|
+
if (!pollIntervalMs || !mero || !namespaceId) return;
|
|
2344
|
+
const handle = setInterval(() => void refetch(), pollIntervalMs);
|
|
2345
|
+
return () => clearInterval(handle);
|
|
2346
|
+
}, [pollIntervalMs, mero, namespaceId, refetch]);
|
|
2347
|
+
const rollup = status?.rollup ?? null;
|
|
2348
|
+
const members = status?.members ?? [];
|
|
2349
|
+
return {
|
|
2350
|
+
status,
|
|
2351
|
+
rollup,
|
|
2352
|
+
members,
|
|
2353
|
+
allMigrated: rollup?.allMigrated ?? false,
|
|
2354
|
+
membersPendingSignature: rollup?.membersPendingSignature ?? 0,
|
|
2355
|
+
/** Members whose migrate aborted (migration-check failed or apply errored). */
|
|
2356
|
+
failed: rollup?.failed ?? 0,
|
|
2357
|
+
loading,
|
|
2358
|
+
error,
|
|
2359
|
+
refetch
|
|
2360
|
+
};
|
|
2361
|
+
}
|
|
2362
|
+
function useAppVersion(contextId, expected) {
|
|
2363
|
+
const { mero } = useMero();
|
|
2364
|
+
const [appVersion, setAppVersion] = react.useState(void 0);
|
|
2365
|
+
const [loading, setLoading] = react.useState(false);
|
|
2366
|
+
const [error, setError] = react.useState(null);
|
|
2367
|
+
const mountedRef = useMountedRef();
|
|
2368
|
+
const reqRef = react.useRef(0);
|
|
2369
|
+
const refetch = react.useCallback(async () => {
|
|
2370
|
+
if (!mero || !contextId) {
|
|
2371
|
+
if (mountedRef.current) {
|
|
2372
|
+
setAppVersion(void 0);
|
|
2373
|
+
setError(null);
|
|
2374
|
+
setLoading(false);
|
|
2375
|
+
}
|
|
2376
|
+
return;
|
|
2377
|
+
}
|
|
2378
|
+
const seq = ++reqRef.current;
|
|
2379
|
+
if (mountedRef.current) {
|
|
2380
|
+
setLoading(true);
|
|
2381
|
+
setError(null);
|
|
2382
|
+
}
|
|
2383
|
+
try {
|
|
2384
|
+
const context = await mero.admin.getContext(contextId);
|
|
2385
|
+
if (mountedRef.current && seq === reqRef.current) {
|
|
2386
|
+
setAppVersion(context.applicationVersion);
|
|
2387
|
+
}
|
|
2388
|
+
} catch (err) {
|
|
2389
|
+
const errorValue = toError(err);
|
|
2390
|
+
if (mountedRef.current && seq === reqRef.current) {
|
|
2391
|
+
setError(errorValue);
|
|
2392
|
+
}
|
|
2393
|
+
} finally {
|
|
2394
|
+
if (mountedRef.current && seq === reqRef.current) {
|
|
2395
|
+
setLoading(false);
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
}, [contextId, mero, mountedRef]);
|
|
2399
|
+
react.useEffect(() => {
|
|
2400
|
+
setAppVersion(void 0);
|
|
2401
|
+
setError(null);
|
|
2402
|
+
}, [contextId]);
|
|
2403
|
+
react.useEffect(() => {
|
|
2404
|
+
void refetch();
|
|
2405
|
+
}, [refetch]);
|
|
2406
|
+
react.useEffect(() => {
|
|
2407
|
+
if (!mero?.events || !contextId) return;
|
|
2408
|
+
const off = mero.events.onAppVersionChanged((event) => {
|
|
2409
|
+
if (event.contextId !== contextId) return;
|
|
2410
|
+
if (mountedRef.current && event.toVersion) {
|
|
2411
|
+
reqRef.current += 1;
|
|
2412
|
+
setAppVersion(event.toVersion);
|
|
2413
|
+
}
|
|
2414
|
+
});
|
|
2415
|
+
return off;
|
|
2416
|
+
}, [mero, contextId, mountedRef]);
|
|
2417
|
+
const isStale = appVersion != null && expected != null && appVersion !== expected;
|
|
2418
|
+
return { appVersion, expected, isStale, loading, error, refetch };
|
|
2419
|
+
}
|
|
2420
|
+
function useLatestVersion(registryUrl, packageName, currentVersion) {
|
|
2421
|
+
const { mero } = useMero();
|
|
2422
|
+
const [versions, setVersions] = react.useState([]);
|
|
2423
|
+
const [loading, setLoading] = react.useState(false);
|
|
2424
|
+
const [error, setError] = react.useState(null);
|
|
2425
|
+
const mountedRef = useMountedRef();
|
|
2426
|
+
const reqRef = react.useRef(0);
|
|
2427
|
+
const refetch = react.useCallback(async () => {
|
|
2428
|
+
if (!mero || !registryUrl || !packageName) {
|
|
2429
|
+
reqRef.current += 1;
|
|
2430
|
+
if (mountedRef.current) {
|
|
2431
|
+
setVersions([]);
|
|
2432
|
+
setError(null);
|
|
2433
|
+
setLoading(false);
|
|
2434
|
+
}
|
|
2435
|
+
return;
|
|
2436
|
+
}
|
|
2437
|
+
const seq = ++reqRef.current;
|
|
2438
|
+
if (mountedRef.current) {
|
|
2439
|
+
setLoading(true);
|
|
2440
|
+
setError(null);
|
|
2441
|
+
}
|
|
2442
|
+
try {
|
|
2443
|
+
const result = await mero.admin.getRegistryVersions(registryUrl, packageName);
|
|
2444
|
+
if (mountedRef.current && seq === reqRef.current) {
|
|
2445
|
+
setVersions(result);
|
|
2446
|
+
}
|
|
2447
|
+
} catch (err) {
|
|
2448
|
+
const errorValue = toError(err);
|
|
2449
|
+
if (mountedRef.current && seq === reqRef.current) {
|
|
2450
|
+
setError(errorValue);
|
|
2451
|
+
}
|
|
2452
|
+
} finally {
|
|
2453
|
+
if (mountedRef.current && seq === reqRef.current) {
|
|
2454
|
+
setLoading(false);
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
}, [mero, registryUrl, packageName, mountedRef]);
|
|
2458
|
+
react.useEffect(() => {
|
|
2459
|
+
setVersions([]);
|
|
2460
|
+
setError(null);
|
|
2461
|
+
}, [registryUrl, packageName]);
|
|
2462
|
+
react.useEffect(() => {
|
|
2463
|
+
void refetch();
|
|
2464
|
+
}, [refetch]);
|
|
2465
|
+
const latestVersion = versions[0] ?? null;
|
|
2466
|
+
const updateAvailable = latestVersion != null && currentVersion != null && meroJs.compareSemver(latestVersion, currentVersion) > 0;
|
|
2467
|
+
return { versions, latestVersion, currentVersion, updateAvailable, loading, error, refetch };
|
|
2468
|
+
}
|
|
2469
|
+
function useMyAuthoredMigration(contextId) {
|
|
2470
|
+
const { mero } = useMero();
|
|
2471
|
+
const [summary, setSummary] = react.useState(null);
|
|
2472
|
+
const [pendingCount, setPendingCount] = react.useState(0);
|
|
2473
|
+
const mountedRef = useMountedRef();
|
|
2474
|
+
const { loading, error, run } = useAsyncMutation();
|
|
2475
|
+
const reqRef = react.useRef(0);
|
|
2476
|
+
const refresh = react.useCallback(async () => {
|
|
2477
|
+
if (!mero || !contextId) {
|
|
2478
|
+
if (mountedRef.current) setPendingCount(0);
|
|
2479
|
+
return;
|
|
2480
|
+
}
|
|
2481
|
+
const seq = ++reqRef.current;
|
|
2482
|
+
try {
|
|
2483
|
+
const count = await mero.rpc.countMyPending(contextId);
|
|
2484
|
+
if (mountedRef.current && seq === reqRef.current) setPendingCount(count);
|
|
2485
|
+
} catch {
|
|
2486
|
+
}
|
|
2487
|
+
}, [mero, contextId, mountedRef]);
|
|
2488
|
+
react.useEffect(() => {
|
|
2489
|
+
void refresh();
|
|
2490
|
+
}, [refresh]);
|
|
2491
|
+
const authorize = react.useCallback(async () => {
|
|
2492
|
+
if (!mero || !contextId) return null;
|
|
2493
|
+
const result = await run(() => mero.rpc.migrateMyEntries(contextId));
|
|
2494
|
+
if (result && mountedRef.current) {
|
|
2495
|
+
reqRef.current += 1;
|
|
2496
|
+
setSummary(result);
|
|
2497
|
+
setPendingCount(result.remaining);
|
|
2498
|
+
}
|
|
2499
|
+
return result;
|
|
2500
|
+
}, [mero, contextId, run, mountedRef]);
|
|
2501
|
+
return {
|
|
2502
|
+
summary,
|
|
2503
|
+
pendingCount,
|
|
2504
|
+
pending: pendingCount > 0,
|
|
2505
|
+
authorize,
|
|
2506
|
+
loading,
|
|
2507
|
+
error,
|
|
2508
|
+
refresh
|
|
2509
|
+
};
|
|
2510
|
+
}
|
|
2511
|
+
function MigrationPendingBanner({
|
|
2512
|
+
contextId,
|
|
2513
|
+
className,
|
|
2514
|
+
children,
|
|
2515
|
+
onMigrated
|
|
2516
|
+
}) {
|
|
2517
|
+
const { pending, pendingCount, authorize, loading } = useMyAuthoredMigration(contextId);
|
|
2518
|
+
if (!pending) return null;
|
|
2519
|
+
const handleClick = async () => {
|
|
2520
|
+
const result = await authorize();
|
|
2521
|
+
if (result && result.remaining === 0) {
|
|
2522
|
+
onMigrated?.();
|
|
2523
|
+
}
|
|
2524
|
+
};
|
|
2525
|
+
const message = children ?? `You have ${pendingCount} ${pendingCount === 1 ? "entry" : "entries"} to re-sign after a recent upgrade.`;
|
|
2526
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-testid": "migration-pending-banner", role: "status", children: [
|
|
2527
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: message }),
|
|
2528
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: handleClick, disabled: loading, children: loading ? "Migrating\u2026" : "Migrate my data" })
|
|
2529
|
+
] });
|
|
2530
|
+
}
|
|
2531
|
+
function MigrationAdminPanel({ namespaceId, pollIntervalMs, className }) {
|
|
2532
|
+
const { status, rollup, members, membersPendingSignature, failed, error } = useMigrationStatus(
|
|
2533
|
+
namespaceId,
|
|
2534
|
+
{ pollIntervalMs }
|
|
2535
|
+
);
|
|
2536
|
+
if (error && !status) {
|
|
2537
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-testid": "migration-admin-panel", children: [
|
|
2538
|
+
"Failed to load migration status: ",
|
|
2539
|
+
error.message
|
|
2540
|
+
] });
|
|
2541
|
+
}
|
|
2542
|
+
if (!status || !rollup) {
|
|
2543
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-testid": "migration-admin-panel", children: "Loading migration status\u2026" });
|
|
2544
|
+
}
|
|
2545
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-testid": "migration-admin-panel", children: [
|
|
2546
|
+
error && // A poll failed after data was already loaded — keep showing the last
|
|
2547
|
+
// good rollup but flag that it may be stale.
|
|
2548
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-testid": "migration-status-error", role: "alert", children: [
|
|
2549
|
+
"Could not refresh migration status: ",
|
|
2550
|
+
error.message
|
|
2551
|
+
] }),
|
|
2552
|
+
/* @__PURE__ */ jsxRuntime.jsxs("dl", { children: [
|
|
2553
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2554
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { children: "Target version" }),
|
|
2555
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: status.targetVersion })
|
|
2556
|
+
] }),
|
|
2557
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2558
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { children: "Migrated" }),
|
|
2559
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: rollup.migrated })
|
|
2560
|
+
] }),
|
|
2561
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2562
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { children: "In progress" }),
|
|
2563
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: rollup.inProgress })
|
|
2564
|
+
] }),
|
|
2565
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2566
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { children: "Unknown" }),
|
|
2567
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: rollup.unknown })
|
|
2568
|
+
] }),
|
|
2569
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2570
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { children: "Failed" }),
|
|
2571
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { "data-testid": "migration-failed-count", children: failed })
|
|
2572
|
+
] }),
|
|
2573
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2574
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { children: "Total" }),
|
|
2575
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: rollup.total })
|
|
2576
|
+
] }),
|
|
2577
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2578
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { children: "All migrated" }),
|
|
2579
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: rollup.allMigrated ? "yes" : "no" })
|
|
2580
|
+
] }),
|
|
2581
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2582
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { children: "Members pending signature" }),
|
|
2583
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { "data-testid": "members-pending-signature", children: membersPendingSignature })
|
|
2584
|
+
] })
|
|
2585
|
+
] }),
|
|
2586
|
+
/* @__PURE__ */ jsxRuntime.jsxs("table", { children: [
|
|
2587
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2588
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { children: "Peer" }),
|
|
2589
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { children: "State" }),
|
|
2590
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { children: "Schema" }),
|
|
2591
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { children: "Pending" }),
|
|
2592
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { children: "Reason" })
|
|
2593
|
+
] }) }),
|
|
2594
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: members.map((m) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { "data-testid": "migration-member-row", children: [
|
|
2595
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { children: m.peer }),
|
|
2596
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { children: m.state }),
|
|
2597
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { children: m.report?.schemaVersion ?? "\u2014" }),
|
|
2598
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { children: m.report?.authoredRemaining ?? "\u2014" }),
|
|
2599
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { children: m.report?.migrationFailed ?? "\u2014" })
|
|
2600
|
+
] }, m.peer)) })
|
|
2601
|
+
] })
|
|
2602
|
+
] });
|
|
2603
|
+
}
|
|
2297
2604
|
|
|
2298
2605
|
Object.defineProperty(exports, "CAPABILITIES", {
|
|
2299
2606
|
enumerable: true,
|
|
@@ -2319,6 +2626,8 @@ exports.LoginModal = LoginModal;
|
|
|
2319
2626
|
exports.MERO_CSS_VARS = MERO_CSS_VARS;
|
|
2320
2627
|
exports.MeroContext = MeroContext;
|
|
2321
2628
|
exports.MeroProvider = MeroProvider;
|
|
2629
|
+
exports.MigrationAdminPanel = MigrationAdminPanel;
|
|
2630
|
+
exports.MigrationPendingBanner = MigrationPendingBanner;
|
|
2322
2631
|
exports.clearAllStorage = clearAllStorage;
|
|
2323
2632
|
exports.clearApplicationId = clearApplicationId;
|
|
2324
2633
|
exports.clearContextId = clearContextId;
|
|
@@ -2338,6 +2647,7 @@ exports.setContextIdentity = setContextIdentity;
|
|
|
2338
2647
|
exports.setNodeUrl = setNodeUrl;
|
|
2339
2648
|
exports.themeToCssVars = themeToCssVars;
|
|
2340
2649
|
exports.useAddGroupMembers = useAddGroupMembers;
|
|
2650
|
+
exports.useAppVersion = useAppVersion;
|
|
2341
2651
|
exports.useApplicationContexts = useApplicationContexts;
|
|
2342
2652
|
exports.useContextDiscovery = useContextDiscovery;
|
|
2343
2653
|
exports.useContextGroup = useContextGroup;
|
|
@@ -2363,8 +2673,11 @@ exports.useJoinContext = useJoinContext;
|
|
|
2363
2673
|
exports.useJoinGroup = useJoinGroup;
|
|
2364
2674
|
exports.useJoinNamespace = useJoinNamespace;
|
|
2365
2675
|
exports.useJoinSubgroupInheritance = useJoinSubgroupInheritance;
|
|
2676
|
+
exports.useLatestVersion = useLatestVersion;
|
|
2366
2677
|
exports.useMemberMetadata = useMemberMetadata;
|
|
2367
2678
|
exports.useMero = useMero;
|
|
2679
|
+
exports.useMigrationStatus = useMigrationStatus;
|
|
2680
|
+
exports.useMyAuthoredMigration = useMyAuthoredMigration;
|
|
2368
2681
|
exports.useNamespace = useNamespace;
|
|
2369
2682
|
exports.useNamespaceGroups = useNamespaceGroups;
|
|
2370
2683
|
exports.useNamespaceIdentity = useNamespaceIdentity;
|