@calimero-network/mero-react 2.4.0 → 2.5.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.d.cts CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
- import React__default, { CSSProperties } from 'react';
3
+ import React__default, { CSSProperties, ReactNode } from 'react';
4
4
  import * as _calimero_network_mero_js from '@calimero-network/mero-js';
5
- import { MeroJs, SetMetadataRequest, AddGroupMembersRequest, CreateContextRequest, CreateGroupInNamespaceRequest, CreateNamespaceRequest, CreateNamespaceInvitationRequest, CreateNamespaceInvitationResponseData, CreateRecursiveInvitationResponseData, DeleteGroupRequest, DeleteNamespaceRequest, DetachContextFromGroupRequest, GroupContextEntry, GroupInfo, CreateGroupInvitationRequest, GroupMember, MetadataRecord, GroupUpgradeStatusResponseData, JoinGroupRequest, JoinNamespaceRequest, Namespace, SubgroupEntry, NamespaceIdentity, NestGroupRequest, RegisterGroupSigningKeyRequest, RemoveGroupMembersRequest, RetryGroupUpgradeRequest, SetDefaultCapabilitiesRequest, SetSubgroupVisibilityRequest, SetTeeAdmissionPolicyRequest, SseEventData, SyncGroupRequest, UnnestGroupRequest, UpdateGroupSettingsRequest, UpdateMemberRoleRequest, UpgradeGroupRequest, TokenData } from '@calimero-network/mero-js';
5
+ import { MeroJs, SetMetadataRequest, AddGroupMembersRequest, CreateContextRequest, CreateGroupInNamespaceRequest, CreateNamespaceRequest, CreateNamespaceInvitationRequest, CreateNamespaceInvitationResponseData, CreateRecursiveInvitationResponseData, DeleteGroupRequest, DeleteNamespaceRequest, DetachContextFromGroupRequest, GroupContextEntry, GroupInfo, CreateGroupInvitationRequest, GroupMember, MetadataRecord, GroupUpgradeStatusResponseData, JoinGroupRequest, JoinNamespaceRequest, MigrationStatus, MigrationStatusRollup, MemberMigrationStatusEntry, MigrateMyEntriesSummary, Namespace, SubgroupEntry, NamespaceIdentity, NestGroupRequest, RegisterGroupSigningKeyRequest, RemoveGroupMembersRequest, RetryGroupUpgradeRequest, SetDefaultCapabilitiesRequest, SetSubgroupVisibilityRequest, SetTeeAdmissionPolicyRequest, SseEventData, SyncGroupRequest, UnnestGroupRequest, UpdateGroupSettingsRequest, UpdateMemberRoleRequest, UpgradeGroupRequest, TokenData } from '@calimero-network/mero-js';
6
6
  export * from '@calimero-network/mero-js';
7
7
  export { CAPABILITIES, MetadataRecord, hasCap, withCap, withoutCap } from '@calimero-network/mero-js';
8
8
 
@@ -267,6 +267,36 @@ interface CalimeroLogoProps extends React__default.SVGAttributes<SVGSVGElement>
267
267
  }
268
268
  declare function CalimeroLogo({ size, color, style, ...rest }: CalimeroLogoProps): react_jsx_runtime.JSX.Element;
269
269
 
270
+ interface MigrationPendingBannerProps {
271
+ /** Context whose authored entries to check / convert. */
272
+ contextId: string;
273
+ className?: string;
274
+ /** Override the default prompt text. */
275
+ children?: ReactNode;
276
+ /** Fired once a convert leaves nothing pending (`remaining === 0`). */
277
+ onMigrated?: () => void;
278
+ }
279
+ /**
280
+ * Shows only when the current identity has entries below the target schema
281
+ * (skew #1). A single button runs the one-tap `migrate_my_entries` convert and
282
+ * the banner clears itself once nothing is pending.
283
+ */
284
+ declare function MigrationPendingBanner({ contextId, className, children, onMigrated, }: MigrationPendingBannerProps): react_jsx_runtime.JSX.Element | null;
285
+
286
+ interface MigrationAdminPanelProps {
287
+ /** Namespace whose migration rollup to display. */
288
+ namespaceId: string;
289
+ /** Re-fetch interval; migration facts arrive via heartbeat gossip. */
290
+ pollIntervalMs?: number;
291
+ className?: string;
292
+ }
293
+ /**
294
+ * Operator view of a namespace's migration rollup (skew #3): the cohort
295
+ * counters, `membersPendingSignature`, and a per-member table. Read-only —
296
+ * pair with the upgrade-trigger hooks to drive a migration.
297
+ */
298
+ declare function MigrationAdminPanel({ namespaceId, pollIntervalMs, className }: MigrationAdminPanelProps): react_jsx_runtime.JSX.Element;
299
+
270
300
  /**
271
301
  * Shape accepted by the metadata-setter hooks — re-exported from mero-js so
272
302
  * callers have one canonical type. A `set*Metadata` call **replaces the whole
@@ -548,6 +578,52 @@ declare function useDetachContextFromGroup(): {
548
578
  loading: boolean;
549
579
  error: Error | null;
550
580
  };
581
+ /**
582
+ * Migration-status rollup for a namespace (skew #3). Migration facts arrive via
583
+ * heartbeat gossip (no SSE), so liveness is polling: pass `pollIntervalMs` to
584
+ * re-fetch on an interval. Derived counters are null-safe before the first load.
585
+ */
586
+ declare function useMigrationStatus(namespaceId?: string | null, options?: {
587
+ pollIntervalMs?: number;
588
+ }): {
589
+ status: MigrationStatus | null;
590
+ rollup: MigrationStatusRollup | null;
591
+ members: MemberMigrationStatusEntry[];
592
+ allMigrated: boolean;
593
+ membersPendingSignature: number;
594
+ loading: boolean;
595
+ error: Error | null;
596
+ refetch: () => Promise<void>;
597
+ };
598
+ /**
599
+ * Bundle-version skew (#2): reads the context's installed `applicationVersion`
600
+ * (semver) and compares it to the app-declared `expected` build constant. Any
601
+ * mismatch (either direction) is `isStale` → "reload to update". Subscribes to
602
+ * `AppVersionChanged` so a live flip updates `appVersion` without a refetch.
603
+ */
604
+ declare function useAppVersion(contextId?: string | null, expected?: string): {
605
+ appVersion: string | undefined;
606
+ expected: string | undefined;
607
+ isStale: boolean;
608
+ loading: boolean;
609
+ error: Error | null;
610
+ refetch: () => Promise<void>;
611
+ };
612
+ /**
613
+ * The caller's own identity-gated entries pending re-signature (skew #1).
614
+ * `pending` is `pendingCount > 0` (from `count_my_pending`); `authorize()` runs
615
+ * the one-tap `migrate_my_entries` convert and folds the resulting `remaining`
616
+ * back into the count.
617
+ */
618
+ declare function useMyAuthoredMigration(contextId?: string | null): {
619
+ summary: MigrateMyEntriesSummary | null;
620
+ pendingCount: number;
621
+ pending: boolean;
622
+ authorize: () => Promise<MigrateMyEntriesSummary | null>;
623
+ loading: boolean;
624
+ error: Error | null;
625
+ refresh: () => Promise<void>;
626
+ };
551
627
 
552
628
  /**
553
629
  * Storage utilities for mero-react
@@ -613,4 +689,4 @@ declare function clearContextIdentity(): void;
613
689
  */
614
690
  declare function clearAllStorage(): void;
615
691
 
616
- export { type AppContext, AppMode, type ApplicationContextRecord, CalimeroLogo, type CalimeroLogoProps, ConnectButton, type ConnectButtonProps, ConnectionType, type ContextDiscoveryOptions, type ContextDiscoveryState, type CustomConnectionConfig, type ExecutionResult, LoginModal, type LoginModalProps, MERO_CSS_VARS, MeroContext, type MeroContextValue, MeroProvider, type MeroProviderConfig, type MeroProviderProps, type MeroTheme, type ResolvedMeroTheme, type SetMetadataInput, clearAllStorage, clearApplicationId, clearContextId, clearContextIdentity, clearNodeUrl, cssVar, defaultMeroTheme, getApplicationId, getContextId, getContextIdentity, getNodeUrl, localStorageTokenStorage, resolveMeroTheme, setApplicationId, setContextId, setContextIdentity, setNodeUrl, themeToCssVars, useAddGroupMembers, useApplicationContexts, useContextDiscovery, useContextGroup, useContexts, useCreateContext, useCreateGroupInNamespace, useCreateNamespace, useCreateNamespaceInvitation, useDefaultCapabilities, useDeleteContext, useDeleteGroup, useDeleteNamespace, useDetachContextFromGroup, useExecute, useGroupCapabilities, useGroupContexts, useGroupInfo, useGroupInvitations, useGroupMembers, useGroupMetadata, useGroupUpgradeStatus, useJoinContext, useJoinGroup, useJoinNamespace, useJoinSubgroupInheritance, useMemberMetadata, useMero, useNamespace, useNamespaceGroups, useNamespaceIdentity, useNamespaces, useNamespacesForApplication, useNestGroup, useRegisterGroupSigningKey, useRemoveGroupMembers, useRetryGroupUpgrade, useSetContextMetadata, useSetDefaultCapabilities, useSetGroupMetadata, useSetMemberMetadata, useSetSubgroupVisibility, useSetTeeAdmissionPolicy, useSubgroupVisibility, useSubgroups, useSubscription, useSyncGroup, useUnnestGroup, useUpdateGroupSettings, useUpdateMemberRole, useUpgradeGroup };
692
+ export { type AppContext, AppMode, type ApplicationContextRecord, CalimeroLogo, type CalimeroLogoProps, ConnectButton, type ConnectButtonProps, ConnectionType, type ContextDiscoveryOptions, type ContextDiscoveryState, type CustomConnectionConfig, type ExecutionResult, LoginModal, type LoginModalProps, MERO_CSS_VARS, MeroContext, type MeroContextValue, MeroProvider, type MeroProviderConfig, type MeroProviderProps, type MeroTheme, MigrationAdminPanel, type MigrationAdminPanelProps, MigrationPendingBanner, type MigrationPendingBannerProps, type ResolvedMeroTheme, type SetMetadataInput, clearAllStorage, clearApplicationId, clearContextId, clearContextIdentity, clearNodeUrl, cssVar, defaultMeroTheme, getApplicationId, getContextId, getContextIdentity, getNodeUrl, localStorageTokenStorage, resolveMeroTheme, setApplicationId, setContextId, setContextIdentity, setNodeUrl, themeToCssVars, useAddGroupMembers, useAppVersion, useApplicationContexts, useContextDiscovery, useContextGroup, useContexts, useCreateContext, useCreateGroupInNamespace, useCreateNamespace, useCreateNamespaceInvitation, useDefaultCapabilities, useDeleteContext, useDeleteGroup, useDeleteNamespace, useDetachContextFromGroup, useExecute, useGroupCapabilities, useGroupContexts, useGroupInfo, useGroupInvitations, useGroupMembers, useGroupMetadata, useGroupUpgradeStatus, useJoinContext, useJoinGroup, useJoinNamespace, useJoinSubgroupInheritance, useMemberMetadata, useMero, useMigrationStatus, useMyAuthoredMigration, useNamespace, useNamespaceGroups, useNamespaceIdentity, useNamespaces, useNamespacesForApplication, useNestGroup, useRegisterGroupSigningKey, useRemoveGroupMembers, useRetryGroupUpgrade, useSetContextMetadata, useSetDefaultCapabilities, useSetGroupMetadata, useSetMemberMetadata, useSetSubgroupVisibility, useSetTeeAdmissionPolicy, useSubgroupVisibility, useSubgroups, useSubscription, useSyncGroup, useUnnestGroup, useUpdateGroupSettings, useUpdateMemberRole, useUpgradeGroup };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
- import React__default, { CSSProperties } from 'react';
3
+ import React__default, { CSSProperties, ReactNode } from 'react';
4
4
  import * as _calimero_network_mero_js from '@calimero-network/mero-js';
5
- import { MeroJs, SetMetadataRequest, AddGroupMembersRequest, CreateContextRequest, CreateGroupInNamespaceRequest, CreateNamespaceRequest, CreateNamespaceInvitationRequest, CreateNamespaceInvitationResponseData, CreateRecursiveInvitationResponseData, DeleteGroupRequest, DeleteNamespaceRequest, DetachContextFromGroupRequest, GroupContextEntry, GroupInfo, CreateGroupInvitationRequest, GroupMember, MetadataRecord, GroupUpgradeStatusResponseData, JoinGroupRequest, JoinNamespaceRequest, Namespace, SubgroupEntry, NamespaceIdentity, NestGroupRequest, RegisterGroupSigningKeyRequest, RemoveGroupMembersRequest, RetryGroupUpgradeRequest, SetDefaultCapabilitiesRequest, SetSubgroupVisibilityRequest, SetTeeAdmissionPolicyRequest, SseEventData, SyncGroupRequest, UnnestGroupRequest, UpdateGroupSettingsRequest, UpdateMemberRoleRequest, UpgradeGroupRequest, TokenData } from '@calimero-network/mero-js';
5
+ import { MeroJs, SetMetadataRequest, AddGroupMembersRequest, CreateContextRequest, CreateGroupInNamespaceRequest, CreateNamespaceRequest, CreateNamespaceInvitationRequest, CreateNamespaceInvitationResponseData, CreateRecursiveInvitationResponseData, DeleteGroupRequest, DeleteNamespaceRequest, DetachContextFromGroupRequest, GroupContextEntry, GroupInfo, CreateGroupInvitationRequest, GroupMember, MetadataRecord, GroupUpgradeStatusResponseData, JoinGroupRequest, JoinNamespaceRequest, MigrationStatus, MigrationStatusRollup, MemberMigrationStatusEntry, MigrateMyEntriesSummary, Namespace, SubgroupEntry, NamespaceIdentity, NestGroupRequest, RegisterGroupSigningKeyRequest, RemoveGroupMembersRequest, RetryGroupUpgradeRequest, SetDefaultCapabilitiesRequest, SetSubgroupVisibilityRequest, SetTeeAdmissionPolicyRequest, SseEventData, SyncGroupRequest, UnnestGroupRequest, UpdateGroupSettingsRequest, UpdateMemberRoleRequest, UpgradeGroupRequest, TokenData } from '@calimero-network/mero-js';
6
6
  export * from '@calimero-network/mero-js';
7
7
  export { CAPABILITIES, MetadataRecord, hasCap, withCap, withoutCap } from '@calimero-network/mero-js';
8
8
 
@@ -267,6 +267,36 @@ interface CalimeroLogoProps extends React__default.SVGAttributes<SVGSVGElement>
267
267
  }
268
268
  declare function CalimeroLogo({ size, color, style, ...rest }: CalimeroLogoProps): react_jsx_runtime.JSX.Element;
269
269
 
270
+ interface MigrationPendingBannerProps {
271
+ /** Context whose authored entries to check / convert. */
272
+ contextId: string;
273
+ className?: string;
274
+ /** Override the default prompt text. */
275
+ children?: ReactNode;
276
+ /** Fired once a convert leaves nothing pending (`remaining === 0`). */
277
+ onMigrated?: () => void;
278
+ }
279
+ /**
280
+ * Shows only when the current identity has entries below the target schema
281
+ * (skew #1). A single button runs the one-tap `migrate_my_entries` convert and
282
+ * the banner clears itself once nothing is pending.
283
+ */
284
+ declare function MigrationPendingBanner({ contextId, className, children, onMigrated, }: MigrationPendingBannerProps): react_jsx_runtime.JSX.Element | null;
285
+
286
+ interface MigrationAdminPanelProps {
287
+ /** Namespace whose migration rollup to display. */
288
+ namespaceId: string;
289
+ /** Re-fetch interval; migration facts arrive via heartbeat gossip. */
290
+ pollIntervalMs?: number;
291
+ className?: string;
292
+ }
293
+ /**
294
+ * Operator view of a namespace's migration rollup (skew #3): the cohort
295
+ * counters, `membersPendingSignature`, and a per-member table. Read-only —
296
+ * pair with the upgrade-trigger hooks to drive a migration.
297
+ */
298
+ declare function MigrationAdminPanel({ namespaceId, pollIntervalMs, className }: MigrationAdminPanelProps): react_jsx_runtime.JSX.Element;
299
+
270
300
  /**
271
301
  * Shape accepted by the metadata-setter hooks — re-exported from mero-js so
272
302
  * callers have one canonical type. A `set*Metadata` call **replaces the whole
@@ -548,6 +578,52 @@ declare function useDetachContextFromGroup(): {
548
578
  loading: boolean;
549
579
  error: Error | null;
550
580
  };
581
+ /**
582
+ * Migration-status rollup for a namespace (skew #3). Migration facts arrive via
583
+ * heartbeat gossip (no SSE), so liveness is polling: pass `pollIntervalMs` to
584
+ * re-fetch on an interval. Derived counters are null-safe before the first load.
585
+ */
586
+ declare function useMigrationStatus(namespaceId?: string | null, options?: {
587
+ pollIntervalMs?: number;
588
+ }): {
589
+ status: MigrationStatus | null;
590
+ rollup: MigrationStatusRollup | null;
591
+ members: MemberMigrationStatusEntry[];
592
+ allMigrated: boolean;
593
+ membersPendingSignature: number;
594
+ loading: boolean;
595
+ error: Error | null;
596
+ refetch: () => Promise<void>;
597
+ };
598
+ /**
599
+ * Bundle-version skew (#2): reads the context's installed `applicationVersion`
600
+ * (semver) and compares it to the app-declared `expected` build constant. Any
601
+ * mismatch (either direction) is `isStale` → "reload to update". Subscribes to
602
+ * `AppVersionChanged` so a live flip updates `appVersion` without a refetch.
603
+ */
604
+ declare function useAppVersion(contextId?: string | null, expected?: string): {
605
+ appVersion: string | undefined;
606
+ expected: string | undefined;
607
+ isStale: boolean;
608
+ loading: boolean;
609
+ error: Error | null;
610
+ refetch: () => Promise<void>;
611
+ };
612
+ /**
613
+ * The caller's own identity-gated entries pending re-signature (skew #1).
614
+ * `pending` is `pendingCount > 0` (from `count_my_pending`); `authorize()` runs
615
+ * the one-tap `migrate_my_entries` convert and folds the resulting `remaining`
616
+ * back into the count.
617
+ */
618
+ declare function useMyAuthoredMigration(contextId?: string | null): {
619
+ summary: MigrateMyEntriesSummary | null;
620
+ pendingCount: number;
621
+ pending: boolean;
622
+ authorize: () => Promise<MigrateMyEntriesSummary | null>;
623
+ loading: boolean;
624
+ error: Error | null;
625
+ refresh: () => Promise<void>;
626
+ };
551
627
 
552
628
  /**
553
629
  * Storage utilities for mero-react
@@ -613,4 +689,4 @@ declare function clearContextIdentity(): void;
613
689
  */
614
690
  declare function clearAllStorage(): void;
615
691
 
616
- export { type AppContext, AppMode, type ApplicationContextRecord, CalimeroLogo, type CalimeroLogoProps, ConnectButton, type ConnectButtonProps, ConnectionType, type ContextDiscoveryOptions, type ContextDiscoveryState, type CustomConnectionConfig, type ExecutionResult, LoginModal, type LoginModalProps, MERO_CSS_VARS, MeroContext, type MeroContextValue, MeroProvider, type MeroProviderConfig, type MeroProviderProps, type MeroTheme, type ResolvedMeroTheme, type SetMetadataInput, clearAllStorage, clearApplicationId, clearContextId, clearContextIdentity, clearNodeUrl, cssVar, defaultMeroTheme, getApplicationId, getContextId, getContextIdentity, getNodeUrl, localStorageTokenStorage, resolveMeroTheme, setApplicationId, setContextId, setContextIdentity, setNodeUrl, themeToCssVars, useAddGroupMembers, useApplicationContexts, useContextDiscovery, useContextGroup, useContexts, useCreateContext, useCreateGroupInNamespace, useCreateNamespace, useCreateNamespaceInvitation, useDefaultCapabilities, useDeleteContext, useDeleteGroup, useDeleteNamespace, useDetachContextFromGroup, useExecute, useGroupCapabilities, useGroupContexts, useGroupInfo, useGroupInvitations, useGroupMembers, useGroupMetadata, useGroupUpgradeStatus, useJoinContext, useJoinGroup, useJoinNamespace, useJoinSubgroupInheritance, useMemberMetadata, useMero, useNamespace, useNamespaceGroups, useNamespaceIdentity, useNamespaces, useNamespacesForApplication, useNestGroup, useRegisterGroupSigningKey, useRemoveGroupMembers, useRetryGroupUpgrade, useSetContextMetadata, useSetDefaultCapabilities, useSetGroupMetadata, useSetMemberMetadata, useSetSubgroupVisibility, useSetTeeAdmissionPolicy, useSubgroupVisibility, useSubgroups, useSubscription, useSyncGroup, useUnnestGroup, useUpdateGroupSettings, useUpdateMemberRole, useUpgradeGroup };
692
+ export { type AppContext, AppMode, type ApplicationContextRecord, CalimeroLogo, type CalimeroLogoProps, ConnectButton, type ConnectButtonProps, ConnectionType, type ContextDiscoveryOptions, type ContextDiscoveryState, type CustomConnectionConfig, type ExecutionResult, LoginModal, type LoginModalProps, MERO_CSS_VARS, MeroContext, type MeroContextValue, MeroProvider, type MeroProviderConfig, type MeroProviderProps, type MeroTheme, MigrationAdminPanel, type MigrationAdminPanelProps, MigrationPendingBanner, type MigrationPendingBannerProps, type ResolvedMeroTheme, type SetMetadataInput, clearAllStorage, clearApplicationId, clearContextId, clearContextIdentity, clearNodeUrl, cssVar, defaultMeroTheme, getApplicationId, getContextId, getContextIdentity, getNodeUrl, localStorageTokenStorage, resolveMeroTheme, setApplicationId, setContextId, setContextIdentity, setNodeUrl, themeToCssVars, useAddGroupMembers, useAppVersion, useApplicationContexts, useContextDiscovery, useContextGroup, useContexts, useCreateContext, useCreateGroupInNamespace, useCreateNamespace, useCreateNamespaceInvitation, useDefaultCapabilities, useDeleteContext, useDeleteGroup, useDeleteNamespace, useDetachContextFromGroup, useExecute, useGroupCapabilities, useGroupContexts, useGroupInfo, useGroupInvitations, useGroupMembers, useGroupMetadata, useGroupUpgradeStatus, useJoinContext, useJoinGroup, useJoinNamespace, useJoinSubgroupInheritance, useMemberMetadata, useMero, useMigrationStatus, useMyAuthoredMigration, useNamespace, useNamespaceGroups, useNamespaceIdentity, useNamespaces, useNamespacesForApplication, useNestGroup, useRegisterGroupSigningKey, useRemoveGroupMembers, useRetryGroupUpgrade, useSetContextMetadata, useSetDefaultCapabilities, useSetGroupMetadata, useSetMemberMetadata, useSetSubgroupVisibility, useSetTeeAdmissionPolicy, useSubgroupVisibility, useSubgroups, useSubscription, useSyncGroup, useUnnestGroup, useUpdateGroupSettings, useUpdateMemberRole, useUpgradeGroup };
package/dist/index.js CHANGED
@@ -2294,7 +2294,257 @@ 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] = useState(null);
2300
+ const [loading, setLoading] = useState(false);
2301
+ const [error, setError] = useState(null);
2302
+ const mountedRef = useMountedRef();
2303
+ const reqRef = useRef(0);
2304
+ const refetch = 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
+ useEffect(() => {
2335
+ setStatus(null);
2336
+ setError(null);
2337
+ }, [namespaceId]);
2338
+ useEffect(() => {
2339
+ void refetch();
2340
+ }, [refetch]);
2341
+ const pollIntervalMs = options?.pollIntervalMs;
2342
+ 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
+ loading,
2356
+ error,
2357
+ refetch
2358
+ };
2359
+ }
2360
+ function useAppVersion(contextId, expected) {
2361
+ const { mero } = useMero();
2362
+ const [appVersion, setAppVersion] = useState(void 0);
2363
+ const [loading, setLoading] = useState(false);
2364
+ const [error, setError] = useState(null);
2365
+ const mountedRef = useMountedRef();
2366
+ const reqRef = useRef(0);
2367
+ const refetch = useCallback(async () => {
2368
+ if (!mero || !contextId) {
2369
+ if (mountedRef.current) {
2370
+ setAppVersion(void 0);
2371
+ setError(null);
2372
+ setLoading(false);
2373
+ }
2374
+ return;
2375
+ }
2376
+ const seq = ++reqRef.current;
2377
+ if (mountedRef.current) {
2378
+ setLoading(true);
2379
+ setError(null);
2380
+ }
2381
+ try {
2382
+ const context = await mero.admin.getContext(contextId);
2383
+ if (mountedRef.current && seq === reqRef.current) {
2384
+ setAppVersion(context.applicationVersion);
2385
+ }
2386
+ } catch (err) {
2387
+ const errorValue = toError(err);
2388
+ if (mountedRef.current && seq === reqRef.current) {
2389
+ setError(errorValue);
2390
+ }
2391
+ } finally {
2392
+ if (mountedRef.current && seq === reqRef.current) {
2393
+ setLoading(false);
2394
+ }
2395
+ }
2396
+ }, [contextId, mero, mountedRef]);
2397
+ useEffect(() => {
2398
+ setAppVersion(void 0);
2399
+ setError(null);
2400
+ }, [contextId]);
2401
+ useEffect(() => {
2402
+ void refetch();
2403
+ }, [refetch]);
2404
+ useEffect(() => {
2405
+ if (!mero?.events || !contextId) return;
2406
+ const off = mero.events.onAppVersionChanged((event) => {
2407
+ if (event.contextId !== contextId) return;
2408
+ if (mountedRef.current && event.toVersion) {
2409
+ reqRef.current += 1;
2410
+ setAppVersion(event.toVersion);
2411
+ }
2412
+ });
2413
+ return off;
2414
+ }, [mero, contextId, mountedRef]);
2415
+ const isStale = appVersion != null && expected != null && appVersion !== expected;
2416
+ return { appVersion, expected, isStale, loading, error, refetch };
2417
+ }
2418
+ function useMyAuthoredMigration(contextId) {
2419
+ const { mero } = useMero();
2420
+ const [summary, setSummary] = useState(null);
2421
+ const [pendingCount, setPendingCount] = useState(0);
2422
+ const mountedRef = useMountedRef();
2423
+ const { loading, error, run } = useAsyncMutation();
2424
+ const reqRef = useRef(0);
2425
+ const refresh = useCallback(async () => {
2426
+ if (!mero || !contextId) {
2427
+ if (mountedRef.current) setPendingCount(0);
2428
+ return;
2429
+ }
2430
+ const seq = ++reqRef.current;
2431
+ try {
2432
+ const count = await mero.rpc.countMyPending(contextId);
2433
+ if (mountedRef.current && seq === reqRef.current) setPendingCount(count);
2434
+ } catch {
2435
+ }
2436
+ }, [mero, contextId, mountedRef]);
2437
+ useEffect(() => {
2438
+ void refresh();
2439
+ }, [refresh]);
2440
+ const authorize = useCallback(async () => {
2441
+ if (!mero || !contextId) return null;
2442
+ const result = await run(() => mero.rpc.migrateMyEntries(contextId));
2443
+ if (result && mountedRef.current) {
2444
+ reqRef.current += 1;
2445
+ setSummary(result);
2446
+ setPendingCount(result.remaining);
2447
+ }
2448
+ return result;
2449
+ }, [mero, contextId, run, mountedRef]);
2450
+ return {
2451
+ summary,
2452
+ pendingCount,
2453
+ pending: pendingCount > 0,
2454
+ authorize,
2455
+ loading,
2456
+ error,
2457
+ refresh
2458
+ };
2459
+ }
2460
+ function MigrationPendingBanner({
2461
+ contextId,
2462
+ className,
2463
+ children,
2464
+ onMigrated
2465
+ }) {
2466
+ const { pending, pendingCount, authorize, loading } = useMyAuthoredMigration(contextId);
2467
+ if (!pending) return null;
2468
+ const handleClick = async () => {
2469
+ const result = await authorize();
2470
+ if (result && result.remaining === 0) {
2471
+ onMigrated?.();
2472
+ }
2473
+ };
2474
+ const message = children ?? `You have ${pendingCount} ${pendingCount === 1 ? "entry" : "entries"} to re-sign after a recent upgrade.`;
2475
+ return /* @__PURE__ */ jsxs("div", { className, "data-testid": "migration-pending-banner", role: "status", children: [
2476
+ /* @__PURE__ */ jsx("span", { children: message }),
2477
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: handleClick, disabled: loading, children: loading ? "Migrating\u2026" : "Migrate my data" })
2478
+ ] });
2479
+ }
2480
+ function MigrationAdminPanel({ namespaceId, pollIntervalMs, className }) {
2481
+ const { status, rollup, members, membersPendingSignature, error } = useMigrationStatus(
2482
+ namespaceId,
2483
+ { pollIntervalMs }
2484
+ );
2485
+ if (error && !status) {
2486
+ return /* @__PURE__ */ jsxs("div", { className, "data-testid": "migration-admin-panel", children: [
2487
+ "Failed to load migration status: ",
2488
+ error.message
2489
+ ] });
2490
+ }
2491
+ if (!status || !rollup) {
2492
+ return /* @__PURE__ */ jsx("div", { className, "data-testid": "migration-admin-panel", children: "Loading migration status\u2026" });
2493
+ }
2494
+ return /* @__PURE__ */ jsxs("div", { className, "data-testid": "migration-admin-panel", children: [
2495
+ error && // A poll failed after data was already loaded — keep showing the last
2496
+ // good rollup but flag that it may be stale.
2497
+ /* @__PURE__ */ jsxs("div", { "data-testid": "migration-status-error", role: "alert", children: [
2498
+ "Could not refresh migration status: ",
2499
+ error.message
2500
+ ] }),
2501
+ /* @__PURE__ */ jsxs("dl", { children: [
2502
+ /* @__PURE__ */ jsxs("div", { children: [
2503
+ /* @__PURE__ */ jsx("dt", { children: "Target version" }),
2504
+ /* @__PURE__ */ jsx("dd", { children: status.targetVersion })
2505
+ ] }),
2506
+ /* @__PURE__ */ jsxs("div", { children: [
2507
+ /* @__PURE__ */ jsx("dt", { children: "Migrated" }),
2508
+ /* @__PURE__ */ jsx("dd", { children: rollup.migrated })
2509
+ ] }),
2510
+ /* @__PURE__ */ jsxs("div", { children: [
2511
+ /* @__PURE__ */ jsx("dt", { children: "In progress" }),
2512
+ /* @__PURE__ */ jsx("dd", { children: rollup.inProgress })
2513
+ ] }),
2514
+ /* @__PURE__ */ jsxs("div", { children: [
2515
+ /* @__PURE__ */ jsx("dt", { children: "Unknown" }),
2516
+ /* @__PURE__ */ jsx("dd", { children: rollup.unknown })
2517
+ ] }),
2518
+ /* @__PURE__ */ jsxs("div", { children: [
2519
+ /* @__PURE__ */ jsx("dt", { children: "Total" }),
2520
+ /* @__PURE__ */ jsx("dd", { children: rollup.total })
2521
+ ] }),
2522
+ /* @__PURE__ */ jsxs("div", { children: [
2523
+ /* @__PURE__ */ jsx("dt", { children: "All migrated" }),
2524
+ /* @__PURE__ */ jsx("dd", { children: rollup.allMigrated ? "yes" : "no" })
2525
+ ] }),
2526
+ /* @__PURE__ */ jsxs("div", { children: [
2527
+ /* @__PURE__ */ jsx("dt", { children: "Members pending signature" }),
2528
+ /* @__PURE__ */ jsx("dd", { "data-testid": "members-pending-signature", children: membersPendingSignature })
2529
+ ] })
2530
+ ] }),
2531
+ /* @__PURE__ */ jsxs("table", { children: [
2532
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
2533
+ /* @__PURE__ */ jsx("th", { children: "Peer" }),
2534
+ /* @__PURE__ */ jsx("th", { children: "State" }),
2535
+ /* @__PURE__ */ jsx("th", { children: "Schema" }),
2536
+ /* @__PURE__ */ jsx("th", { children: "Pending" })
2537
+ ] }) }),
2538
+ /* @__PURE__ */ jsx("tbody", { children: members.map((m) => /* @__PURE__ */ jsxs("tr", { "data-testid": "migration-member-row", children: [
2539
+ /* @__PURE__ */ jsx("td", { children: m.peer }),
2540
+ /* @__PURE__ */ jsx("td", { children: m.state }),
2541
+ /* @__PURE__ */ jsx("td", { children: m.report?.schemaVersion ?? "\u2014" }),
2542
+ /* @__PURE__ */ jsx("td", { children: m.report?.authoredRemaining ?? "\u2014" })
2543
+ ] }, m.peer)) })
2544
+ ] })
2545
+ ] });
2546
+ }
2297
2547
 
2298
- export { AppMode, CalimeroLogo, ConnectButton, ConnectionType, LoginModal, MERO_CSS_VARS, MeroContext, MeroProvider, clearAllStorage, clearApplicationId, clearContextId, clearContextIdentity, clearNodeUrl, cssVar, defaultMeroTheme, getApplicationId, getContextId, getContextIdentity, getNodeUrl, localStorageTokenStorage, resolveMeroTheme, setApplicationId, setContextId, setContextIdentity, setNodeUrl, themeToCssVars, useAddGroupMembers, useApplicationContexts, useContextDiscovery, useContextGroup, useContexts, useCreateContext, useCreateGroupInNamespace, useCreateNamespace, useCreateNamespaceInvitation, useDefaultCapabilities, useDeleteContext, useDeleteGroup, useDeleteNamespace, useDetachContextFromGroup, useExecute, useGroupCapabilities, useGroupContexts, useGroupInfo, useGroupInvitations, useGroupMembers, useGroupMetadata, useGroupUpgradeStatus, useJoinContext, useJoinGroup, useJoinNamespace, useJoinSubgroupInheritance, useMemberMetadata, useMero, useNamespace, useNamespaceGroups, useNamespaceIdentity, useNamespaces, useNamespacesForApplication, useNestGroup, useRegisterGroupSigningKey, useRemoveGroupMembers, useRetryGroupUpgrade, useSetContextMetadata, useSetDefaultCapabilities, useSetGroupMetadata, useSetMemberMetadata, useSetSubgroupVisibility, useSetTeeAdmissionPolicy, useSubgroupVisibility, useSubgroups, useSubscription, useSyncGroup, useUnnestGroup, useUpdateGroupSettings, useUpdateMemberRole, useUpgradeGroup };
2548
+ export { AppMode, CalimeroLogo, ConnectButton, ConnectionType, LoginModal, MERO_CSS_VARS, MeroContext, MeroProvider, MigrationAdminPanel, MigrationPendingBanner, clearAllStorage, clearApplicationId, clearContextId, clearContextIdentity, clearNodeUrl, cssVar, defaultMeroTheme, getApplicationId, getContextId, getContextIdentity, getNodeUrl, localStorageTokenStorage, resolveMeroTheme, setApplicationId, setContextId, setContextIdentity, setNodeUrl, themeToCssVars, useAddGroupMembers, useAppVersion, useApplicationContexts, useContextDiscovery, useContextGroup, useContexts, useCreateContext, useCreateGroupInNamespace, useCreateNamespace, useCreateNamespaceInvitation, useDefaultCapabilities, useDeleteContext, useDeleteGroup, useDeleteNamespace, useDetachContextFromGroup, useExecute, useGroupCapabilities, useGroupContexts, useGroupInfo, useGroupInvitations, useGroupMembers, useGroupMetadata, useGroupUpgradeStatus, useJoinContext, useJoinGroup, useJoinNamespace, useJoinSubgroupInheritance, useMemberMetadata, useMero, useMigrationStatus, useMyAuthoredMigration, useNamespace, useNamespaceGroups, useNamespaceIdentity, useNamespaces, useNamespacesForApplication, useNestGroup, useRegisterGroupSigningKey, useRemoveGroupMembers, useRetryGroupUpgrade, useSetContextMetadata, useSetDefaultCapabilities, useSetGroupMetadata, useSetMemberMetadata, useSetSubgroupVisibility, useSetTeeAdmissionPolicy, useSubgroupVisibility, useSubgroups, useSubscription, useSyncGroup, useUnnestGroup, useUpdateGroupSettings, useUpdateMemberRole, useUpgradeGroup };
2299
2549
  //# sourceMappingURL=index.js.map
2300
2550
  //# sourceMappingURL=index.js.map