@calimero-network/mero-react 4.0.0 → 4.1.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/README.md +3 -1
- package/dist/index.cjs +311 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +56 -2
- package/dist/index.d.ts +56 -2
- package/dist/index.js +307 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -274,11 +274,17 @@ interface LoginModalProps {
|
|
|
274
274
|
isOpen: boolean;
|
|
275
275
|
/** Theme overrides — accepts any subset of `MeroTheme` tokens */
|
|
276
276
|
theme?: MeroTheme;
|
|
277
|
+
/**
|
|
278
|
+
* Ports probed when discovering remote/local nodes. Defaults to the
|
|
279
|
+
* well-known Calimero dev ports (2428, 2429, 2528, 2529). Mostly an escape
|
|
280
|
+
* hatch for non-standard setups and tests.
|
|
281
|
+
*/
|
|
282
|
+
localNodePorts?: readonly number[];
|
|
277
283
|
}
|
|
278
284
|
/**
|
|
279
285
|
* LoginModal - Connection modal component
|
|
280
286
|
*/
|
|
281
|
-
declare function LoginModal({ onConnect, onClose, connectionType, isOpen, theme, }: LoginModalProps): React.ReactPortal | null;
|
|
287
|
+
declare function LoginModal({ onConnect, onClose, connectionType, isOpen, theme, localNodePorts, }: LoginModalProps): React.ReactPortal | null;
|
|
282
288
|
|
|
283
289
|
interface CalimeroLogoProps extends React__default.SVGAttributes<SVGSVGElement> {
|
|
284
290
|
/** Width / height shorthand (applied to both). Default: 24. */
|
|
@@ -316,6 +322,54 @@ interface MigrationAdminPanelProps {
|
|
|
316
322
|
*/
|
|
317
323
|
declare function MigrationAdminPanel({ namespaceId, pollIntervalMs, className }: MigrationAdminPanelProps): react_jsx_runtime.JSX.Element;
|
|
318
324
|
|
|
325
|
+
/**
|
|
326
|
+
* Local-node discovery.
|
|
327
|
+
*
|
|
328
|
+
* Calimero dev/desktop nodes expose a public, unauthenticated health endpoint
|
|
329
|
+
* at `GET {nodeUrl}/admin-api/health` that returns `{ "data": { "status":
|
|
330
|
+
* "alive" } }`. The most common local layouts run on a small, well-known set of
|
|
331
|
+
* ports, so instead of forcing the user to type a URL we probe those ports and
|
|
332
|
+
* offer whatever is actually running.
|
|
333
|
+
*/
|
|
334
|
+
/**
|
|
335
|
+
* Default ports probed when discovering local nodes. Covers the two-node dev
|
|
336
|
+
* stacks used across the Calimero apps (RPC + alt ports for node1 / node2).
|
|
337
|
+
*/
|
|
338
|
+
declare const DEFAULT_LOCAL_NODE_PORTS: readonly [2428, 2429, 2528, 2529];
|
|
339
|
+
interface DiscoverLocalNodesOptions {
|
|
340
|
+
/** Ports to probe. Defaults to {@link DEFAULT_LOCAL_NODE_PORTS}. */
|
|
341
|
+
ports?: readonly number[];
|
|
342
|
+
/** Per-probe timeout in ms. Defaults to 2000. */
|
|
343
|
+
timeoutMs?: number;
|
|
344
|
+
/** Abort the whole discovery (e.g. when the modal closes). */
|
|
345
|
+
signal?: AbortSignal;
|
|
346
|
+
}
|
|
347
|
+
/** Build the canonical base URL for a local node on the given port. */
|
|
348
|
+
declare function localNodeUrl(port: number): string;
|
|
349
|
+
/**
|
|
350
|
+
* Resolve an API `path` against a node `baseUrl`. Ensures the base ends with a
|
|
351
|
+
* slash first, so a base that carries a path prefix (e.g. a `NODE_PATH_PREFIX`
|
|
352
|
+
* deployment like `http://host/node1`) keeps that segment instead of having it
|
|
353
|
+
* stripped by relative URL resolution.
|
|
354
|
+
*/
|
|
355
|
+
declare function nodeEndpoint(baseUrl: string, path: string): string;
|
|
356
|
+
/**
|
|
357
|
+
* Probe a single node's health endpoint. Resolves `true` only when the node
|
|
358
|
+
* answers with a 2xx and (when the body is JSON) reports a non-dead status.
|
|
359
|
+
* Any network error, timeout, or non-ok response resolves `false` — never
|
|
360
|
+
* throws (except on an external abort, which is swallowed as `false`).
|
|
361
|
+
*/
|
|
362
|
+
declare function probeNodeHealth(baseUrl: string, options?: {
|
|
363
|
+
timeoutMs?: number;
|
|
364
|
+
signal?: AbortSignal;
|
|
365
|
+
}): Promise<boolean>;
|
|
366
|
+
/**
|
|
367
|
+
* Probe the configured local ports in parallel and return the base URLs that
|
|
368
|
+
* responded as healthy, in the same order as the `ports` argument (which
|
|
369
|
+
* defaults to ascending). Returns an empty array when nothing local is running.
|
|
370
|
+
*/
|
|
371
|
+
declare function discoverLocalNodes(options?: DiscoverLocalNodesOptions): Promise<string[]>;
|
|
372
|
+
|
|
319
373
|
/**
|
|
320
374
|
* Shape accepted by the metadata-setter hooks — re-exported from mero-js so
|
|
321
375
|
* callers have one canonical type. A `set*Metadata` call **replaces the whole
|
|
@@ -734,4 +788,4 @@ declare function clearContextIdentity(): void;
|
|
|
734
788
|
*/
|
|
735
789
|
declare function clearAllStorage(): void;
|
|
736
790
|
|
|
737
|
-
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, useLatestVersion, useMemberMetadata, useMero, useMigrationStatus, useMyAuthoredMigration, useNamespace, useNamespaceGroups, useNamespaceIdentity, useNamespaces, useNamespacesForApplication, useRegisterGroupSigningKey, useRemoveGroupMembers, useReparentGroup, useResyncContext, useRetryGroupUpgrade, useSetContextMetadata, useSetDefaultCapabilities, useSetGroupMetadata, useSetMemberMetadata, useSetSubgroupVisibility, useSetTeeAdmissionPolicy, useSubgroupVisibility, useSubgroups, useSubscription, useSyncGroup, useUpdateGroupSettings, useUpdateMemberRole, useUpgradeGroup };
|
|
791
|
+
export { type AppContext, AppMode, type ApplicationContextRecord, CalimeroLogo, type CalimeroLogoProps, ConnectButton, type ConnectButtonProps, ConnectionType, type ContextDiscoveryOptions, type ContextDiscoveryState, type CustomConnectionConfig, DEFAULT_LOCAL_NODE_PORTS, type DiscoverLocalNodesOptions, 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, discoverLocalNodes, getApplicationId, getContextId, getContextIdentity, getNodeUrl, localNodeUrl, localStorageTokenStorage, nodeEndpoint, probeNodeHealth, 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, useLatestVersion, useMemberMetadata, useMero, useMigrationStatus, useMyAuthoredMigration, useNamespace, useNamespaceGroups, useNamespaceIdentity, useNamespaces, useNamespacesForApplication, useRegisterGroupSigningKey, useRemoveGroupMembers, useReparentGroup, useResyncContext, useRetryGroupUpgrade, useSetContextMetadata, useSetDefaultCapabilities, useSetGroupMetadata, useSetMemberMetadata, useSetSubgroupVisibility, useSetTeeAdmissionPolicy, useSubgroupVisibility, useSubgroups, useSubscription, useSyncGroup, useUpdateGroupSettings, useUpdateMemberRole, useUpgradeGroup };
|
package/dist/index.d.ts
CHANGED
|
@@ -274,11 +274,17 @@ interface LoginModalProps {
|
|
|
274
274
|
isOpen: boolean;
|
|
275
275
|
/** Theme overrides — accepts any subset of `MeroTheme` tokens */
|
|
276
276
|
theme?: MeroTheme;
|
|
277
|
+
/**
|
|
278
|
+
* Ports probed when discovering remote/local nodes. Defaults to the
|
|
279
|
+
* well-known Calimero dev ports (2428, 2429, 2528, 2529). Mostly an escape
|
|
280
|
+
* hatch for non-standard setups and tests.
|
|
281
|
+
*/
|
|
282
|
+
localNodePorts?: readonly number[];
|
|
277
283
|
}
|
|
278
284
|
/**
|
|
279
285
|
* LoginModal - Connection modal component
|
|
280
286
|
*/
|
|
281
|
-
declare function LoginModal({ onConnect, onClose, connectionType, isOpen, theme, }: LoginModalProps): React.ReactPortal | null;
|
|
287
|
+
declare function LoginModal({ onConnect, onClose, connectionType, isOpen, theme, localNodePorts, }: LoginModalProps): React.ReactPortal | null;
|
|
282
288
|
|
|
283
289
|
interface CalimeroLogoProps extends React__default.SVGAttributes<SVGSVGElement> {
|
|
284
290
|
/** Width / height shorthand (applied to both). Default: 24. */
|
|
@@ -316,6 +322,54 @@ interface MigrationAdminPanelProps {
|
|
|
316
322
|
*/
|
|
317
323
|
declare function MigrationAdminPanel({ namespaceId, pollIntervalMs, className }: MigrationAdminPanelProps): react_jsx_runtime.JSX.Element;
|
|
318
324
|
|
|
325
|
+
/**
|
|
326
|
+
* Local-node discovery.
|
|
327
|
+
*
|
|
328
|
+
* Calimero dev/desktop nodes expose a public, unauthenticated health endpoint
|
|
329
|
+
* at `GET {nodeUrl}/admin-api/health` that returns `{ "data": { "status":
|
|
330
|
+
* "alive" } }`. The most common local layouts run on a small, well-known set of
|
|
331
|
+
* ports, so instead of forcing the user to type a URL we probe those ports and
|
|
332
|
+
* offer whatever is actually running.
|
|
333
|
+
*/
|
|
334
|
+
/**
|
|
335
|
+
* Default ports probed when discovering local nodes. Covers the two-node dev
|
|
336
|
+
* stacks used across the Calimero apps (RPC + alt ports for node1 / node2).
|
|
337
|
+
*/
|
|
338
|
+
declare const DEFAULT_LOCAL_NODE_PORTS: readonly [2428, 2429, 2528, 2529];
|
|
339
|
+
interface DiscoverLocalNodesOptions {
|
|
340
|
+
/** Ports to probe. Defaults to {@link DEFAULT_LOCAL_NODE_PORTS}. */
|
|
341
|
+
ports?: readonly number[];
|
|
342
|
+
/** Per-probe timeout in ms. Defaults to 2000. */
|
|
343
|
+
timeoutMs?: number;
|
|
344
|
+
/** Abort the whole discovery (e.g. when the modal closes). */
|
|
345
|
+
signal?: AbortSignal;
|
|
346
|
+
}
|
|
347
|
+
/** Build the canonical base URL for a local node on the given port. */
|
|
348
|
+
declare function localNodeUrl(port: number): string;
|
|
349
|
+
/**
|
|
350
|
+
* Resolve an API `path` against a node `baseUrl`. Ensures the base ends with a
|
|
351
|
+
* slash first, so a base that carries a path prefix (e.g. a `NODE_PATH_PREFIX`
|
|
352
|
+
* deployment like `http://host/node1`) keeps that segment instead of having it
|
|
353
|
+
* stripped by relative URL resolution.
|
|
354
|
+
*/
|
|
355
|
+
declare function nodeEndpoint(baseUrl: string, path: string): string;
|
|
356
|
+
/**
|
|
357
|
+
* Probe a single node's health endpoint. Resolves `true` only when the node
|
|
358
|
+
* answers with a 2xx and (when the body is JSON) reports a non-dead status.
|
|
359
|
+
* Any network error, timeout, or non-ok response resolves `false` — never
|
|
360
|
+
* throws (except on an external abort, which is swallowed as `false`).
|
|
361
|
+
*/
|
|
362
|
+
declare function probeNodeHealth(baseUrl: string, options?: {
|
|
363
|
+
timeoutMs?: number;
|
|
364
|
+
signal?: AbortSignal;
|
|
365
|
+
}): Promise<boolean>;
|
|
366
|
+
/**
|
|
367
|
+
* Probe the configured local ports in parallel and return the base URLs that
|
|
368
|
+
* responded as healthy, in the same order as the `ports` argument (which
|
|
369
|
+
* defaults to ascending). Returns an empty array when nothing local is running.
|
|
370
|
+
*/
|
|
371
|
+
declare function discoverLocalNodes(options?: DiscoverLocalNodesOptions): Promise<string[]>;
|
|
372
|
+
|
|
319
373
|
/**
|
|
320
374
|
* Shape accepted by the metadata-setter hooks — re-exported from mero-js so
|
|
321
375
|
* callers have one canonical type. A `set*Metadata` call **replaces the whole
|
|
@@ -734,4 +788,4 @@ declare function clearContextIdentity(): void;
|
|
|
734
788
|
*/
|
|
735
789
|
declare function clearAllStorage(): void;
|
|
736
790
|
|
|
737
|
-
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, useLatestVersion, useMemberMetadata, useMero, useMigrationStatus, useMyAuthoredMigration, useNamespace, useNamespaceGroups, useNamespaceIdentity, useNamespaces, useNamespacesForApplication, useRegisterGroupSigningKey, useRemoveGroupMembers, useReparentGroup, useResyncContext, useRetryGroupUpgrade, useSetContextMetadata, useSetDefaultCapabilities, useSetGroupMetadata, useSetMemberMetadata, useSetSubgroupVisibility, useSetTeeAdmissionPolicy, useSubgroupVisibility, useSubgroups, useSubscription, useSyncGroup, useUpdateGroupSettings, useUpdateMemberRole, useUpgradeGroup };
|
|
791
|
+
export { type AppContext, AppMode, type ApplicationContextRecord, CalimeroLogo, type CalimeroLogoProps, ConnectButton, type ConnectButtonProps, ConnectionType, type ContextDiscoveryOptions, type ContextDiscoveryState, type CustomConnectionConfig, DEFAULT_LOCAL_NODE_PORTS, type DiscoverLocalNodesOptions, 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, discoverLocalNodes, getApplicationId, getContextId, getContextIdentity, getNodeUrl, localNodeUrl, localStorageTokenStorage, nodeEndpoint, probeNodeHealth, 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, useLatestVersion, useMemberMetadata, useMero, useMigrationStatus, useMyAuthoredMigration, useNamespace, useNamespaceGroups, useNamespaceIdentity, useNamespaces, useNamespacesForApplication, useRegisterGroupSigningKey, useRemoveGroupMembers, useReparentGroup, useResyncContext, useRetryGroupUpgrade, useSetContextMetadata, useSetDefaultCapabilities, useSetGroupMetadata, useSetMemberMetadata, useSetSubgroupVisibility, useSetTeeAdmissionPolicy, useSubgroupVisibility, useSubgroups, useSubscription, useSyncGroup, useUpdateGroupSettings, useUpdateMemberRole, useUpgradeGroup };
|
package/dist/index.js
CHANGED
|
@@ -473,6 +473,59 @@ function CalimeroLogo({
|
|
|
473
473
|
);
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
+
// src/utils/nodeDiscovery.ts
|
|
477
|
+
var DEFAULT_LOCAL_NODE_PORTS = [2428, 2429, 2528, 2529];
|
|
478
|
+
var LOCAL_HOST = "localhost";
|
|
479
|
+
var DEFAULT_PROBE_TIMEOUT_MS = 2e3;
|
|
480
|
+
function localNodeUrl(port) {
|
|
481
|
+
return `http://${LOCAL_HOST}:${port}`;
|
|
482
|
+
}
|
|
483
|
+
function nodeEndpoint(baseUrl, path) {
|
|
484
|
+
const base = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
485
|
+
return new URL(path, base).toString();
|
|
486
|
+
}
|
|
487
|
+
async function probeNodeHealth(baseUrl, options = {}) {
|
|
488
|
+
const { timeoutMs = DEFAULT_PROBE_TIMEOUT_MS, signal } = options;
|
|
489
|
+
if (signal?.aborted) return false;
|
|
490
|
+
const controller = new AbortController();
|
|
491
|
+
const onAbort = () => controller.abort();
|
|
492
|
+
const listenerAdded = !!signal;
|
|
493
|
+
if (listenerAdded) signal.addEventListener("abort", onAbort, { once: true });
|
|
494
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
495
|
+
try {
|
|
496
|
+
const url = nodeEndpoint(baseUrl, "admin-api/health");
|
|
497
|
+
const res = await fetch(url, {
|
|
498
|
+
method: "GET",
|
|
499
|
+
signal: controller.signal
|
|
500
|
+
});
|
|
501
|
+
if (!res.ok) return false;
|
|
502
|
+
try {
|
|
503
|
+
const body = await res.json();
|
|
504
|
+
const status = body?.data?.status !== void 0 ? body?.data?.status : body?.status;
|
|
505
|
+
if (status === void 0) return true;
|
|
506
|
+
return typeof status === "string" && status.toLowerCase() === "alive";
|
|
507
|
+
} catch {
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
} catch {
|
|
511
|
+
return false;
|
|
512
|
+
} finally {
|
|
513
|
+
clearTimeout(timer);
|
|
514
|
+
if (listenerAdded) signal.removeEventListener("abort", onAbort);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
async function discoverLocalNodes(options = {}) {
|
|
518
|
+
const { ports = DEFAULT_LOCAL_NODE_PORTS, timeoutMs, signal } = options;
|
|
519
|
+
const results = await Promise.all(
|
|
520
|
+
ports.map(async (port) => {
|
|
521
|
+
const url = localNodeUrl(port);
|
|
522
|
+
const ok = await probeNodeHealth(url, { timeoutMs, signal });
|
|
523
|
+
return ok ? url : null;
|
|
524
|
+
})
|
|
525
|
+
);
|
|
526
|
+
return results.filter((url) => url !== null);
|
|
527
|
+
}
|
|
528
|
+
|
|
476
529
|
// src/theme.ts
|
|
477
530
|
var defaultMeroTheme = Object.freeze({
|
|
478
531
|
primary: "#a5ff11",
|
|
@@ -521,6 +574,8 @@ function themeToCssVars(theme) {
|
|
|
521
574
|
function cssVar(theme, key) {
|
|
522
575
|
return `var(${MERO_CSS_VARS[key]}, ${theme[key]})`;
|
|
523
576
|
}
|
|
577
|
+
var DEFAULT_LOCAL_NODE_URL = "http://node1.127.0.0.1.nip.io";
|
|
578
|
+
var CUSTOM_SELECTION = "__custom__";
|
|
524
579
|
function isValidUrl(urlString) {
|
|
525
580
|
if (!urlString || urlString.trim() === "") {
|
|
526
581
|
return false;
|
|
@@ -549,6 +604,9 @@ function isValidUrl(urlString) {
|
|
|
549
604
|
return false;
|
|
550
605
|
}
|
|
551
606
|
}
|
|
607
|
+
function displayNodeUrl(url) {
|
|
608
|
+
return url.replace(/^https?:\/\//, "").replace(/\/+$/, "");
|
|
609
|
+
}
|
|
552
610
|
function tint(color, percent) {
|
|
553
611
|
return `color-mix(in srgb, ${color} ${percent}%, transparent)`;
|
|
554
612
|
}
|
|
@@ -653,10 +711,60 @@ function buildStyles(t) {
|
|
|
653
711
|
transition: "all 0.15s ease"
|
|
654
712
|
},
|
|
655
713
|
radioLabelActive: {
|
|
656
|
-
|
|
714
|
+
border: `1px solid ${accent}`,
|
|
715
|
+
backgroundColor: accentGlow,
|
|
716
|
+
color: text
|
|
717
|
+
},
|
|
718
|
+
radioList: {
|
|
719
|
+
display: "flex",
|
|
720
|
+
flexDirection: "column",
|
|
721
|
+
gap: "0.5rem",
|
|
722
|
+
marginBottom: "1rem"
|
|
723
|
+
},
|
|
724
|
+
radioItem: {
|
|
725
|
+
display: "flex",
|
|
726
|
+
alignItems: "center",
|
|
727
|
+
gap: "0.625rem",
|
|
728
|
+
color: text,
|
|
729
|
+
cursor: "pointer",
|
|
730
|
+
padding: "0.75rem 1rem",
|
|
731
|
+
borderRadius: radius,
|
|
732
|
+
border: `1px solid ${border}`,
|
|
733
|
+
backgroundColor: bgSecondary,
|
|
734
|
+
transition: "all 0.15s ease",
|
|
735
|
+
fontSize: "0.875rem"
|
|
736
|
+
},
|
|
737
|
+
radioItemActive: {
|
|
738
|
+
// Override the full `border` shorthand (not just borderColor) so React
|
|
739
|
+
// never has to mix shorthand + longhand on the same element.
|
|
740
|
+
border: `1px solid ${accent}`,
|
|
657
741
|
backgroundColor: accentGlow,
|
|
658
742
|
color: text
|
|
659
743
|
},
|
|
744
|
+
radioIndicator: {
|
|
745
|
+
flexShrink: 0,
|
|
746
|
+
width: "1rem",
|
|
747
|
+
height: "1rem",
|
|
748
|
+
borderRadius: "50%",
|
|
749
|
+
border: `2px solid ${border}`,
|
|
750
|
+
display: "flex",
|
|
751
|
+
alignItems: "center",
|
|
752
|
+
justifyContent: "center"
|
|
753
|
+
},
|
|
754
|
+
radioIndicatorActive: {
|
|
755
|
+
border: `2px solid ${accent}`
|
|
756
|
+
},
|
|
757
|
+
radioDot: {
|
|
758
|
+
width: "0.5rem",
|
|
759
|
+
height: "0.5rem",
|
|
760
|
+
borderRadius: "50%",
|
|
761
|
+
backgroundColor: accent
|
|
762
|
+
},
|
|
763
|
+
nodeMeta: {
|
|
764
|
+
marginLeft: "auto",
|
|
765
|
+
fontSize: "0.75rem",
|
|
766
|
+
color: textSecondary
|
|
767
|
+
},
|
|
660
768
|
input: {
|
|
661
769
|
width: "100%",
|
|
662
770
|
padding: "0.75rem 1rem",
|
|
@@ -682,6 +790,29 @@ function buildStyles(t) {
|
|
|
682
790
|
localInfoCode: {
|
|
683
791
|
color: accent
|
|
684
792
|
},
|
|
793
|
+
noNodeInfo: {
|
|
794
|
+
color: textSecondary,
|
|
795
|
+
fontSize: "0.875rem",
|
|
796
|
+
textAlign: "center",
|
|
797
|
+
padding: "0.75rem",
|
|
798
|
+
backgroundColor: bgSecondary,
|
|
799
|
+
borderRadius: radius,
|
|
800
|
+
marginBottom: "1rem",
|
|
801
|
+
border: `1px solid ${border}`
|
|
802
|
+
},
|
|
803
|
+
toolbar: {
|
|
804
|
+
display: "flex",
|
|
805
|
+
justifyContent: "center",
|
|
806
|
+
marginBottom: "1rem"
|
|
807
|
+
},
|
|
808
|
+
rescan: {
|
|
809
|
+
background: "none",
|
|
810
|
+
border: "none",
|
|
811
|
+
color: accent,
|
|
812
|
+
cursor: "pointer",
|
|
813
|
+
fontSize: "0.8125rem",
|
|
814
|
+
padding: "0.25rem 0.5rem"
|
|
815
|
+
},
|
|
685
816
|
buttonGroup: {
|
|
686
817
|
display: "flex",
|
|
687
818
|
justifyContent: "center"
|
|
@@ -709,6 +840,15 @@ function buildStyles(t) {
|
|
|
709
840
|
padding: "2rem",
|
|
710
841
|
color: textSecondary
|
|
711
842
|
},
|
|
843
|
+
discovering: {
|
|
844
|
+
display: "flex",
|
|
845
|
+
flexDirection: "column",
|
|
846
|
+
alignItems: "center",
|
|
847
|
+
gap: "0.75rem",
|
|
848
|
+
padding: "1rem",
|
|
849
|
+
color: textSecondary,
|
|
850
|
+
fontSize: "0.875rem"
|
|
851
|
+
},
|
|
712
852
|
spinner: {
|
|
713
853
|
width: "2rem",
|
|
714
854
|
height: "2rem",
|
|
@@ -716,6 +856,14 @@ function buildStyles(t) {
|
|
|
716
856
|
borderTopColor: accent,
|
|
717
857
|
borderRadius: "50%",
|
|
718
858
|
animation: "meroSpin 1s linear infinite"
|
|
859
|
+
},
|
|
860
|
+
spinnerSmall: {
|
|
861
|
+
width: "1.5rem",
|
|
862
|
+
height: "1.5rem",
|
|
863
|
+
border: `3px solid ${border}`,
|
|
864
|
+
borderTopColor: accent,
|
|
865
|
+
borderRadius: "50%",
|
|
866
|
+
animation: "meroSpin 1s linear infinite"
|
|
719
867
|
}
|
|
720
868
|
};
|
|
721
869
|
}
|
|
@@ -724,11 +872,14 @@ function LoginModal({
|
|
|
724
872
|
onClose,
|
|
725
873
|
connectionType,
|
|
726
874
|
isOpen,
|
|
727
|
-
theme
|
|
875
|
+
theme,
|
|
876
|
+
localNodePorts = DEFAULT_LOCAL_NODE_PORTS
|
|
728
877
|
}) {
|
|
729
878
|
const [nodeType, setNodeType] = useState("local");
|
|
730
|
-
const [
|
|
731
|
-
const [
|
|
879
|
+
const [selected, setSelected] = useState(CUSTOM_SELECTION);
|
|
880
|
+
const [discovered, setDiscovered] = useState([]);
|
|
881
|
+
const [discovering, setDiscovering] = useState(false);
|
|
882
|
+
const [customUrl, setCustomUrl] = useState("");
|
|
732
883
|
const [loading, setLoading] = useState(false);
|
|
733
884
|
const [error, setError] = useState(null);
|
|
734
885
|
const resolved = useMemo(() => resolveMeroTheme(theme), [theme]);
|
|
@@ -743,7 +894,7 @@ function LoginModal({
|
|
|
743
894
|
useEffect(() => {
|
|
744
895
|
const savedUrl = localStorage.getItem("mero:node_url");
|
|
745
896
|
if (savedUrl) {
|
|
746
|
-
|
|
897
|
+
setCustomUrl(savedUrl);
|
|
747
898
|
}
|
|
748
899
|
}, []);
|
|
749
900
|
useEffect(() => {
|
|
@@ -753,25 +904,56 @@ function LoginModal({
|
|
|
753
904
|
setNodeType("remote");
|
|
754
905
|
}
|
|
755
906
|
}, [connectionType]);
|
|
907
|
+
const [scanNonce, setScanNonce] = useState(0);
|
|
908
|
+
const portsKey = useMemo(() => localNodePorts.join(","), [localNodePorts]);
|
|
909
|
+
const remoteActive = isOpen && shouldShowRemote && nodeType === "remote";
|
|
756
910
|
useEffect(() => {
|
|
757
|
-
if (
|
|
758
|
-
|
|
759
|
-
} else {
|
|
760
|
-
setIsValid(true);
|
|
911
|
+
if (!remoteActive) {
|
|
912
|
+
return;
|
|
761
913
|
}
|
|
762
|
-
|
|
914
|
+
const controller = new AbortController();
|
|
915
|
+
let active = true;
|
|
916
|
+
setDiscovering(true);
|
|
917
|
+
setDiscovered([]);
|
|
918
|
+
setError(null);
|
|
919
|
+
discoverLocalNodes({ ports: localNodePorts, signal: controller.signal }).then((nodes) => {
|
|
920
|
+
if (!active) return;
|
|
921
|
+
setDiscovered(nodes);
|
|
922
|
+
setSelected(nodes.length > 0 ? nodes[0] : CUSTOM_SELECTION);
|
|
923
|
+
}).catch(() => {
|
|
924
|
+
if (active) setSelected(CUSTOM_SELECTION);
|
|
925
|
+
}).finally(() => {
|
|
926
|
+
if (active) setDiscovering(false);
|
|
927
|
+
});
|
|
928
|
+
return () => {
|
|
929
|
+
active = false;
|
|
930
|
+
controller.abort();
|
|
931
|
+
};
|
|
932
|
+
}, [remoteActive, portsKey, scanNonce]);
|
|
933
|
+
const isCustom = selected === CUSTOM_SELECTION;
|
|
934
|
+
const hasDiscovered = discovered.length > 0;
|
|
935
|
+
const canConnect = !loading && (nodeType === "local" ? true : discovering ? false : isCustom ? isValidUrl(customUrl) : true);
|
|
936
|
+
const canConnectRef = useRef(canConnect);
|
|
937
|
+
canConnectRef.current = canConnect;
|
|
763
938
|
const handleConnect = useCallback(async () => {
|
|
764
|
-
|
|
939
|
+
const targetUrl = nodeType === "local" ? DEFAULT_LOCAL_NODE_URL : selected === CUSTOM_SELECTION ? customUrl : selected;
|
|
940
|
+
const usingDiscovered = nodeType === "remote" && selected !== CUSTOM_SELECTION;
|
|
941
|
+
if (nodeType === "remote" && !usingDiscovered && !isValidUrl(targetUrl)) {
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
const normalizedUrl = targetUrl.replace(/\/+$/, "");
|
|
945
|
+
if (usingDiscovered) {
|
|
946
|
+
onConnect(normalizedUrl);
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
765
949
|
setLoading(true);
|
|
766
950
|
setError(null);
|
|
767
|
-
const baseUrl = nodeType === "local" ? "http://node1.127.0.0.1.nip.io" : nodeUrl;
|
|
768
951
|
try {
|
|
769
952
|
const response = await fetch(
|
|
770
|
-
|
|
953
|
+
nodeEndpoint(normalizedUrl, "admin-api/is-authed")
|
|
771
954
|
);
|
|
772
955
|
if (response.ok || response.status === 401) {
|
|
773
956
|
setLoading(false);
|
|
774
|
-
const normalizedUrl = baseUrl.replace(/\/+$/, "");
|
|
775
957
|
onConnect(normalizedUrl);
|
|
776
958
|
} else {
|
|
777
959
|
throw new Error(`Connection failed: ${response.statusText}`);
|
|
@@ -781,10 +963,108 @@ function LoginModal({
|
|
|
781
963
|
setError("Failed to connect. Please check the URL and try again.");
|
|
782
964
|
setLoading(false);
|
|
783
965
|
}
|
|
784
|
-
}, [
|
|
966
|
+
}, [nodeType, selected, customUrl, onConnect]);
|
|
785
967
|
if (!isOpen) {
|
|
786
968
|
return null;
|
|
787
969
|
}
|
|
970
|
+
const showManualInput = isCustom;
|
|
971
|
+
const renderRadio = (value, label, meta) => {
|
|
972
|
+
const active = selected === value;
|
|
973
|
+
return (
|
|
974
|
+
// Selection is driven solely by the radio input's `onChange` — clicking
|
|
975
|
+
// anywhere on the wrapping label forwards to the input, and keyboard
|
|
976
|
+
// users can tab to / arrow through the (visually hidden but focusable)
|
|
977
|
+
// input. A label `onClick` here would double-fire `setSelected`.
|
|
978
|
+
/* @__PURE__ */ jsxs(
|
|
979
|
+
"label",
|
|
980
|
+
{
|
|
981
|
+
"data-testid": `node-option-${value === CUSTOM_SELECTION ? "custom" : displayNodeUrl(value)}`,
|
|
982
|
+
style: {
|
|
983
|
+
...styles.radioItem,
|
|
984
|
+
...active ? styles.radioItemActive : {}
|
|
985
|
+
},
|
|
986
|
+
children: [
|
|
987
|
+
/* @__PURE__ */ jsx(
|
|
988
|
+
"input",
|
|
989
|
+
{
|
|
990
|
+
type: "radio",
|
|
991
|
+
name: "mero-node",
|
|
992
|
+
value,
|
|
993
|
+
checked: active,
|
|
994
|
+
onChange: () => setSelected(value),
|
|
995
|
+
style: { position: "absolute", opacity: 0 }
|
|
996
|
+
}
|
|
997
|
+
),
|
|
998
|
+
/* @__PURE__ */ jsx(
|
|
999
|
+
"span",
|
|
1000
|
+
{
|
|
1001
|
+
style: {
|
|
1002
|
+
...styles.radioIndicator,
|
|
1003
|
+
...active ? styles.radioIndicatorActive : {}
|
|
1004
|
+
},
|
|
1005
|
+
children: active && /* @__PURE__ */ jsx("span", { style: styles.radioDot })
|
|
1006
|
+
}
|
|
1007
|
+
),
|
|
1008
|
+
label,
|
|
1009
|
+
meta && /* @__PURE__ */ jsx("span", { style: styles.nodeMeta, children: meta })
|
|
1010
|
+
]
|
|
1011
|
+
},
|
|
1012
|
+
value
|
|
1013
|
+
)
|
|
1014
|
+
);
|
|
1015
|
+
};
|
|
1016
|
+
const renderRemoteView = () => {
|
|
1017
|
+
if (discovering) {
|
|
1018
|
+
return /* @__PURE__ */ jsxs("div", { style: styles.discovering, "data-testid": "node-discovering", children: [
|
|
1019
|
+
/* @__PURE__ */ jsx("div", { style: styles.spinnerSmall }),
|
|
1020
|
+
/* @__PURE__ */ jsx("p", { children: "Searching for local nodes..." })
|
|
1021
|
+
] });
|
|
1022
|
+
}
|
|
1023
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1024
|
+
/* @__PURE__ */ jsx("p", { style: styles.info, children: hasDiscovered ? "Select a discovered node, or enter a node URL manually." : "No local node found. Enter a node URL to continue." }),
|
|
1025
|
+
hasDiscovered && /* @__PURE__ */ jsxs(
|
|
1026
|
+
"div",
|
|
1027
|
+
{
|
|
1028
|
+
style: styles.radioList,
|
|
1029
|
+
role: "radiogroup",
|
|
1030
|
+
"aria-label": "Available nodes",
|
|
1031
|
+
children: [
|
|
1032
|
+
discovered.map(
|
|
1033
|
+
(url) => renderRadio(url, displayNodeUrl(url), "local")
|
|
1034
|
+
),
|
|
1035
|
+
renderRadio(CUSTOM_SELECTION, "Enter node URL manually")
|
|
1036
|
+
]
|
|
1037
|
+
}
|
|
1038
|
+
),
|
|
1039
|
+
showManualInput && /* @__PURE__ */ jsx(
|
|
1040
|
+
"input",
|
|
1041
|
+
{
|
|
1042
|
+
type: "text",
|
|
1043
|
+
value: customUrl,
|
|
1044
|
+
onChange: (e) => setCustomUrl(e.target.value),
|
|
1045
|
+
placeholder: "https://your-node-url.calimero.network",
|
|
1046
|
+
style: styles.input,
|
|
1047
|
+
"data-testid": "node-url-input",
|
|
1048
|
+
autoFocus: !hasDiscovered,
|
|
1049
|
+
onKeyDown: (e) => {
|
|
1050
|
+
if (e.key === "Enter" && canConnectRef.current) {
|
|
1051
|
+
handleConnect();
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
),
|
|
1056
|
+
/* @__PURE__ */ jsx("div", { style: styles.toolbar, children: /* @__PURE__ */ jsx(
|
|
1057
|
+
"button",
|
|
1058
|
+
{
|
|
1059
|
+
type: "button",
|
|
1060
|
+
style: styles.rescan,
|
|
1061
|
+
onClick: () => setScanNonce((n) => n + 1),
|
|
1062
|
+
"data-testid": "rescan-button",
|
|
1063
|
+
children: "\u21BB Rescan local nodes"
|
|
1064
|
+
}
|
|
1065
|
+
) })
|
|
1066
|
+
] });
|
|
1067
|
+
};
|
|
788
1068
|
const modalContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
789
1069
|
/* @__PURE__ */ jsx("style", { children: `
|
|
790
1070
|
@keyframes meroSpin { to { transform: rotate(360deg); } }
|
|
@@ -792,7 +1072,7 @@ function LoginModal({
|
|
|
792
1072
|
@keyframes meroSlideIn { from { transform: translateY(-12px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
|
|
793
1073
|
` }),
|
|
794
1074
|
/* @__PURE__ */ jsx("div", { style: { ...themeVars, ...styles.overlay }, onClick: onClose, children: /* @__PURE__ */ jsxs("div", { style: styles.content, onClick: (e) => e.stopPropagation(), children: [
|
|
795
|
-
/* @__PURE__ */ jsx("button", { style: styles.closeButton, onClick: onClose, children: "\xD7" }),
|
|
1075
|
+
/* @__PURE__ */ jsx("button", { style: styles.closeButton, onClick: onClose, "aria-label": "Close", children: "\xD7" }),
|
|
796
1076
|
/* @__PURE__ */ jsxs("div", { style: styles.header, children: [
|
|
797
1077
|
/* @__PURE__ */ jsx(CalimeroLogo, { size: 44, color: cssVar(resolved, "primary") }),
|
|
798
1078
|
/* @__PURE__ */ jsx("h1", { style: styles.title, children: "Connect to Calimero" })
|
|
@@ -801,12 +1081,13 @@ function LoginModal({
|
|
|
801
1081
|
/* @__PURE__ */ jsx("p", { children: "Connecting to node..." }),
|
|
802
1082
|
/* @__PURE__ */ jsx("div", { style: styles.spinner })
|
|
803
1083
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
804
|
-
/* @__PURE__ */ jsx("p", { style: styles.info, children:
|
|
1084
|
+
shouldShowRadioGroup && /* @__PURE__ */ jsx("p", { style: styles.info, children: "Select your Calimero node type to continue." }),
|
|
805
1085
|
error && /* @__PURE__ */ jsx("p", { style: styles.error, children: error }),
|
|
806
1086
|
shouldShowRadioGroup && /* @__PURE__ */ jsxs("div", { style: styles.radioGroup, children: [
|
|
807
1087
|
/* @__PURE__ */ jsxs(
|
|
808
1088
|
"label",
|
|
809
1089
|
{
|
|
1090
|
+
"data-testid": "node-type-local",
|
|
810
1091
|
style: {
|
|
811
1092
|
...styles.radioLabel,
|
|
812
1093
|
...nodeType === "local" ? styles.radioLabelActive : {}
|
|
@@ -830,6 +1111,7 @@ function LoginModal({
|
|
|
830
1111
|
/* @__PURE__ */ jsxs(
|
|
831
1112
|
"label",
|
|
832
1113
|
{
|
|
1114
|
+
"data-testid": "node-type-remote",
|
|
833
1115
|
style: {
|
|
834
1116
|
...styles.radioLabel,
|
|
835
1117
|
...nodeType === "remote" ? styles.radioLabelActive : {}
|
|
@@ -851,34 +1133,22 @@ function LoginModal({
|
|
|
851
1133
|
}
|
|
852
1134
|
)
|
|
853
1135
|
] }),
|
|
854
|
-
/* @__PURE__ */
|
|
855
|
-
"input",
|
|
856
|
-
{
|
|
857
|
-
type: "text",
|
|
858
|
-
value: nodeUrl,
|
|
859
|
-
onChange: (e) => setNodeUrl2(e.target.value),
|
|
860
|
-
placeholder: "https://your-node-url.calimero.network",
|
|
861
|
-
style: styles.input,
|
|
862
|
-
onKeyDown: (e) => {
|
|
863
|
-
if (e.key === "Enter" && isValid) {
|
|
864
|
-
handleConnect();
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
) : shouldShowLocal ? /* @__PURE__ */ jsxs("p", { style: styles.localInfo, children: [
|
|
1136
|
+
nodeType === "local" && shouldShowLocal && /* @__PURE__ */ jsxs("p", { style: styles.localInfo, children: [
|
|
869
1137
|
"Using default local node: ",
|
|
870
1138
|
/* @__PURE__ */ jsx("br", {}),
|
|
871
|
-
/* @__PURE__ */ jsx("code", { style: styles.localInfoCode, children:
|
|
872
|
-
] })
|
|
1139
|
+
/* @__PURE__ */ jsx("code", { style: styles.localInfoCode, children: DEFAULT_LOCAL_NODE_URL })
|
|
1140
|
+
] }),
|
|
1141
|
+
nodeType === "remote" && shouldShowRemote && renderRemoteView(),
|
|
873
1142
|
/* @__PURE__ */ jsx("div", { style: styles.buttonGroup, children: /* @__PURE__ */ jsx(
|
|
874
1143
|
"button",
|
|
875
1144
|
{
|
|
876
1145
|
onClick: handleConnect,
|
|
877
|
-
disabled: !
|
|
1146
|
+
disabled: !canConnect,
|
|
878
1147
|
style: {
|
|
879
1148
|
...styles.button,
|
|
880
|
-
...!
|
|
1149
|
+
...!canConnect ? styles.buttonDisabled : {}
|
|
881
1150
|
},
|
|
1151
|
+
"data-testid": "connect-button",
|
|
882
1152
|
children: "Connect"
|
|
883
1153
|
}
|
|
884
1154
|
) })
|
|
@@ -2650,6 +2920,6 @@ function MigrationAdminPanel({ namespaceId, pollIntervalMs, className }) {
|
|
|
2650
2920
|
] });
|
|
2651
2921
|
}
|
|
2652
2922
|
|
|
2653
|
-
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, useLatestVersion, useMemberMetadata, useMero, useMigrationStatus, useMyAuthoredMigration, useNamespace, useNamespaceGroups, useNamespaceIdentity, useNamespaces, useNamespacesForApplication, useRegisterGroupSigningKey, useRemoveGroupMembers, useReparentGroup, useResyncContext, useRetryGroupUpgrade, useSetContextMetadata, useSetDefaultCapabilities, useSetGroupMetadata, useSetMemberMetadata, useSetSubgroupVisibility, useSetTeeAdmissionPolicy, useSubgroupVisibility, useSubgroups, useSubscription, useSyncGroup, useUpdateGroupSettings, useUpdateMemberRole, useUpgradeGroup };
|
|
2923
|
+
export { AppMode, CalimeroLogo, ConnectButton, ConnectionType, DEFAULT_LOCAL_NODE_PORTS, LoginModal, MERO_CSS_VARS, MeroContext, MeroProvider, MigrationAdminPanel, MigrationPendingBanner, clearAllStorage, clearApplicationId, clearContextId, clearContextIdentity, clearNodeUrl, cssVar, defaultMeroTheme, discoverLocalNodes, getApplicationId, getContextId, getContextIdentity, getNodeUrl, localNodeUrl, localStorageTokenStorage, nodeEndpoint, probeNodeHealth, 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, useLatestVersion, useMemberMetadata, useMero, useMigrationStatus, useMyAuthoredMigration, useNamespace, useNamespaceGroups, useNamespaceIdentity, useNamespaces, useNamespacesForApplication, useRegisterGroupSigningKey, useRemoveGroupMembers, useReparentGroup, useResyncContext, useRetryGroupUpgrade, useSetContextMetadata, useSetDefaultCapabilities, useSetGroupMetadata, useSetMemberMetadata, useSetSubgroupVisibility, useSetTeeAdmissionPolicy, useSubgroupVisibility, useSubgroups, useSubscription, useSyncGroup, useUpdateGroupSettings, useUpdateMemberRole, useUpgradeGroup };
|
|
2654
2924
|
//# sourceMappingURL=index.js.map
|
|
2655
2925
|
//# sourceMappingURL=index.js.map
|