@calimero-network/mero-react 4.1.1 → 4.2.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 CHANGED
@@ -1369,6 +1369,49 @@ function useAsyncMutation() {
1369
1369
  );
1370
1370
  return { loading, error, run, setError };
1371
1371
  }
1372
+ function useAsyncResource(fetcher, initialValue, deps) {
1373
+ const mountedRef = useMountedRef();
1374
+ const [data, setData] = react.useState(initialValue);
1375
+ const [loading, setLoading] = react.useState(false);
1376
+ const [error, setError] = react.useState(null);
1377
+ const reqRef = react.useRef(0);
1378
+ const fetcherRef = react.useRef(fetcher);
1379
+ fetcherRef.current = fetcher;
1380
+ const initialRef = react.useRef(initialValue);
1381
+ const refetch = react.useCallback(async () => {
1382
+ const seq = ++reqRef.current;
1383
+ const fn = fetcherRef.current;
1384
+ if (!fn) {
1385
+ if (mountedRef.current && seq === reqRef.current) {
1386
+ setData(initialRef.current);
1387
+ setError(null);
1388
+ setLoading(false);
1389
+ }
1390
+ return;
1391
+ }
1392
+ if (mountedRef.current) {
1393
+ setLoading(true);
1394
+ setError(null);
1395
+ }
1396
+ try {
1397
+ const result = await fn();
1398
+ if (mountedRef.current && seq === reqRef.current) setData(result);
1399
+ } catch (err) {
1400
+ if (mountedRef.current && seq === reqRef.current) setError(toError(err));
1401
+ } finally {
1402
+ if (mountedRef.current && seq === reqRef.current) setLoading(false);
1403
+ }
1404
+ }, deps);
1405
+ react.useEffect(() => {
1406
+ reqRef.current += 1;
1407
+ setData(initialRef.current);
1408
+ setError(null);
1409
+ }, deps);
1410
+ react.useEffect(() => {
1411
+ void refetch();
1412
+ }, [refetch]);
1413
+ return { data, loading, error, refetch };
1414
+ }
1372
1415
  function sleep(ms) {
1373
1416
  return new Promise((resolve) => {
1374
1417
  setTimeout(resolve, ms);
@@ -1453,123 +1496,42 @@ function useSubscription(contextIds, callback) {
1453
1496
  }
1454
1497
  function useContexts(applicationId) {
1455
1498
  const { mero } = useMero();
1456
- const [contexts, setContexts] = react.useState([]);
1457
- const [loading, setLoading] = react.useState(false);
1458
- const [error, setError] = react.useState(null);
1459
- const mountedRef = useMountedRef();
1460
- const refetch = react.useCallback(async () => {
1461
- if (!mero) return;
1462
- if (mountedRef.current) {
1463
- setLoading(true);
1464
- setError(null);
1465
- }
1466
- try {
1499
+ const { data, loading, error, refetch } = useAsyncResource(
1500
+ mero ? async () => {
1467
1501
  const response = applicationId ? await mero.admin.getContextsForApplication(applicationId) : await mero.admin.getContexts();
1468
- const list = mapApplicationContexts(response.contexts ?? []);
1469
- if (mountedRef.current) {
1470
- setContexts(list);
1471
- }
1472
- } catch (err) {
1473
- const errorValue = toError(err);
1474
- if (mountedRef.current) {
1475
- setError(errorValue);
1476
- }
1477
- } finally {
1478
- if (mountedRef.current) {
1479
- setLoading(false);
1480
- }
1481
- }
1482
- }, [mero, applicationId]);
1483
- react.useEffect(() => {
1484
- void refetch();
1485
- }, [refetch]);
1486
- return { contexts, loading, error, refetch };
1502
+ return mapApplicationContexts(response.contexts ?? []);
1503
+ } : null,
1504
+ [],
1505
+ [mero, applicationId]
1506
+ );
1507
+ return { contexts: data, loading, error, refetch };
1487
1508
  }
1488
1509
  function useApplicationContexts(applicationId) {
1489
1510
  return useContexts(applicationId);
1490
1511
  }
1491
1512
  function useGroupMembers(groupId) {
1492
1513
  const { mero } = useMero();
1493
- const [members, setMembers] = react.useState([]);
1494
- const [selfIdentity, setSelfIdentity] = react.useState(null);
1495
- const [loading, setLoading] = react.useState(false);
1496
- const [error, setError] = react.useState(null);
1497
- const mountedRef = useMountedRef();
1498
- const refetch = react.useCallback(async () => {
1499
- if (!mero || !groupId) {
1500
- if (mountedRef.current) {
1501
- setMembers([]);
1502
- setSelfIdentity(null);
1503
- setError(null);
1504
- setLoading(false);
1505
- }
1506
- return;
1507
- }
1508
- if (mountedRef.current) {
1509
- setLoading(true);
1510
- setError(null);
1511
- }
1512
- try {
1513
- const response = await mero.admin.listGroupMembers(groupId);
1514
- if (mountedRef.current) {
1515
- setMembers(response.members ?? []);
1516
- setSelfIdentity(response.selfIdentity ?? null);
1517
- }
1518
- } catch (err) {
1519
- const errorValue = toError(err);
1520
- if (mountedRef.current) {
1521
- setError(errorValue);
1522
- }
1523
- } finally {
1524
- if (mountedRef.current) {
1525
- setLoading(false);
1526
- }
1527
- }
1528
- }, [groupId, mero, mountedRef]);
1529
- react.useEffect(() => {
1530
- void refetch();
1531
- }, [refetch]);
1532
- return { members, selfIdentity, loading, error, refetch };
1514
+ const { data, loading, error, refetch } = useAsyncResource(
1515
+ mero && groupId ? () => mero.admin.listGroupMembers(groupId) : null,
1516
+ null,
1517
+ [mero, groupId]
1518
+ );
1519
+ return {
1520
+ members: data?.members ?? [],
1521
+ selfIdentity: data?.selfIdentity ?? null,
1522
+ loading,
1523
+ error,
1524
+ refetch
1525
+ };
1533
1526
  }
1534
1527
  function useGroupContexts(groupId) {
1535
1528
  const { mero } = useMero();
1536
- const [contexts, setContexts] = react.useState([]);
1537
- const [loading, setLoading] = react.useState(false);
1538
- const [error, setError] = react.useState(null);
1539
- const mountedRef = useMountedRef();
1540
- const refetch = react.useCallback(async () => {
1541
- if (!mero || !groupId) {
1542
- if (mountedRef.current) {
1543
- setContexts([]);
1544
- setError(null);
1545
- setLoading(false);
1546
- }
1547
- return;
1548
- }
1549
- if (mountedRef.current) {
1550
- setLoading(true);
1551
- setError(null);
1552
- }
1553
- try {
1554
- const nextContexts = await mero.admin.listGroupContexts(groupId);
1555
- if (mountedRef.current) {
1556
- setContexts(nextContexts);
1557
- }
1558
- } catch (err) {
1559
- const errorValue = toError(err);
1560
- if (mountedRef.current) {
1561
- setError(errorValue);
1562
- }
1563
- } finally {
1564
- if (mountedRef.current) {
1565
- setLoading(false);
1566
- }
1567
- }
1568
- }, [groupId, mero, mountedRef]);
1569
- react.useEffect(() => {
1570
- void refetch();
1571
- }, [refetch]);
1572
- return { contexts, loading, error, refetch };
1529
+ const { data, loading, error, refetch } = useAsyncResource(
1530
+ mero && groupId ? () => mero.admin.listGroupContexts(groupId) : null,
1531
+ [],
1532
+ [mero, groupId]
1533
+ );
1534
+ return { contexts: data, loading, error, refetch };
1573
1535
  }
1574
1536
  function useGroupInvitations() {
1575
1537
  const { mero } = useMero();
@@ -1605,9 +1567,11 @@ function useGroupCapabilities(groupId, memberId) {
1605
1567
  const [loading, setLoading] = react.useState(false);
1606
1568
  const [error, setError] = react.useState(null);
1607
1569
  const mountedRef = useMountedRef();
1570
+ const reqRef = react.useRef(0);
1608
1571
  const refetch = react.useCallback(async () => {
1572
+ const seq = ++reqRef.current;
1609
1573
  if (!mero || !groupId || !memberId) {
1610
- if (mountedRef.current) {
1574
+ if (mountedRef.current && seq === reqRef.current) {
1611
1575
  setCapabilitiesState(null);
1612
1576
  setError(null);
1613
1577
  setLoading(false);
@@ -1620,22 +1584,27 @@ function useGroupCapabilities(groupId, memberId) {
1620
1584
  }
1621
1585
  try {
1622
1586
  const response = await mero.admin.getMemberCapabilities(groupId, memberId);
1623
- if (mountedRef.current) {
1587
+ if (mountedRef.current && seq === reqRef.current) {
1624
1588
  setCapabilitiesState(response.capabilities);
1625
1589
  }
1626
1590
  return response.capabilities;
1627
1591
  } catch (err) {
1628
1592
  const errorValue = toError(err);
1629
- if (mountedRef.current) {
1593
+ if (mountedRef.current && seq === reqRef.current) {
1630
1594
  setError(errorValue);
1631
1595
  }
1632
1596
  return null;
1633
1597
  } finally {
1634
- if (mountedRef.current) {
1598
+ if (mountedRef.current && seq === reqRef.current) {
1635
1599
  setLoading(false);
1636
1600
  }
1637
1601
  }
1638
1602
  }, [groupId, memberId, mero, mountedRef]);
1603
+ react.useEffect(() => {
1604
+ reqRef.current += 1;
1605
+ setCapabilitiesState(null);
1606
+ setError(null);
1607
+ }, [groupId, memberId]);
1639
1608
  react.useEffect(() => {
1640
1609
  void refetch();
1641
1610
  }, [refetch]);
@@ -1815,83 +1784,21 @@ function useJoinSubgroupInheritance() {
1815
1784
  }
1816
1785
  function useContextGroup(contextId) {
1817
1786
  const { mero } = useMero();
1818
- const [groupId, setGroupId] = react.useState(null);
1819
- const [loading, setLoading] = react.useState(false);
1820
- const [error, setError] = react.useState(null);
1821
- const mountedRef = useMountedRef();
1822
- const refetch = react.useCallback(async () => {
1823
- if (!mero || !contextId) {
1824
- if (mountedRef.current) {
1825
- setGroupId(null);
1826
- setError(null);
1827
- setLoading(false);
1828
- }
1829
- return;
1830
- }
1831
- if (mountedRef.current) {
1832
- setLoading(true);
1833
- setError(null);
1834
- }
1835
- try {
1836
- const result = await mero.admin.getContextGroup(contextId);
1837
- if (mountedRef.current) {
1838
- setGroupId(result);
1839
- }
1840
- } catch (err) {
1841
- const errorValue = toError(err);
1842
- if (mountedRef.current) {
1843
- setError(errorValue);
1844
- }
1845
- } finally {
1846
- if (mountedRef.current) {
1847
- setLoading(false);
1848
- }
1849
- }
1850
- }, [contextId, mero, mountedRef]);
1851
- react.useEffect(() => {
1852
- void refetch();
1853
- }, [refetch]);
1854
- return { groupId, loading, error, refetch };
1787
+ const { data, loading, error, refetch } = useAsyncResource(
1788
+ mero && contextId ? () => mero.admin.getContextGroup(contextId) : null,
1789
+ null,
1790
+ [mero, contextId]
1791
+ );
1792
+ return { groupId: data, loading, error, refetch };
1855
1793
  }
1856
1794
  function useGroupInfo(groupId) {
1857
1795
  const { mero } = useMero();
1858
- const [groupInfo, setGroupInfo] = react.useState(null);
1859
- const [loading, setLoading] = react.useState(false);
1860
- const [error, setError] = react.useState(null);
1861
- const mountedRef = useMountedRef();
1862
- const refetch = react.useCallback(async () => {
1863
- if (!mero || !groupId) {
1864
- if (mountedRef.current) {
1865
- setGroupInfo(null);
1866
- setError(null);
1867
- setLoading(false);
1868
- }
1869
- return;
1870
- }
1871
- if (mountedRef.current) {
1872
- setLoading(true);
1873
- setError(null);
1874
- }
1875
- try {
1876
- const result = await mero.admin.getGroupInfo(groupId);
1877
- if (mountedRef.current) {
1878
- setGroupInfo(result);
1879
- }
1880
- } catch (err) {
1881
- const errorValue = toError(err);
1882
- if (mountedRef.current) {
1883
- setError(errorValue);
1884
- }
1885
- } finally {
1886
- if (mountedRef.current) {
1887
- setLoading(false);
1888
- }
1889
- }
1890
- }, [groupId, mero, mountedRef]);
1891
- react.useEffect(() => {
1892
- void refetch();
1893
- }, [refetch]);
1894
- return { groupInfo, loading, error, refetch };
1796
+ const { data, loading, error, refetch } = useAsyncResource(
1797
+ mero && groupId ? () => mero.admin.getGroupInfo(groupId) : null,
1798
+ null,
1799
+ [mero, groupId]
1800
+ );
1801
+ return { groupInfo: data, loading, error, refetch };
1895
1802
  }
1896
1803
  function useDeleteGroup() {
1897
1804
  const { mero } = useMero();
@@ -1943,156 +1850,39 @@ function useRemoveGroupMembers() {
1943
1850
  }
1944
1851
  function useNamespaces() {
1945
1852
  const { mero } = useMero();
1946
- const [namespaces, setNamespaces] = react.useState([]);
1947
- const [loading, setLoading] = react.useState(false);
1948
- const [error, setError] = react.useState(null);
1949
- const mountedRef = useMountedRef();
1950
- const refetch = react.useCallback(async () => {
1951
- if (!mero) return;
1952
- if (mountedRef.current) {
1953
- setLoading(true);
1954
- setError(null);
1955
- }
1956
- try {
1957
- const result = await mero.admin.listNamespaces();
1958
- if (mountedRef.current) {
1959
- setNamespaces(result);
1960
- }
1961
- } catch (err) {
1962
- const errorValue = toError(err);
1963
- if (mountedRef.current) {
1964
- setError(errorValue);
1965
- }
1966
- } finally {
1967
- if (mountedRef.current) {
1968
- setLoading(false);
1969
- }
1970
- }
1971
- }, [mero, mountedRef]);
1972
- react.useEffect(() => {
1973
- void refetch();
1974
- }, [refetch]);
1975
- return { namespaces, loading, error, refetch };
1853
+ const { data, loading, error, refetch } = useAsyncResource(
1854
+ mero ? () => mero.admin.listNamespaces() : null,
1855
+ [],
1856
+ [mero]
1857
+ );
1858
+ return { namespaces: data, loading, error, refetch };
1976
1859
  }
1977
1860
  function useNamespace(namespaceId) {
1978
1861
  const { mero } = useMero();
1979
- const [namespace, setNamespace] = react.useState(null);
1980
- const [loading, setLoading] = react.useState(false);
1981
- const [error, setError] = react.useState(null);
1982
- const mountedRef = useMountedRef();
1983
- const refetch = react.useCallback(async () => {
1984
- if (!mero || !namespaceId) {
1985
- if (mountedRef.current) {
1986
- setNamespace(null);
1987
- setError(null);
1988
- setLoading(false);
1989
- }
1990
- return;
1991
- }
1992
- if (mountedRef.current) {
1993
- setLoading(true);
1994
- setError(null);
1995
- }
1996
- try {
1997
- const result = await mero.admin.getNamespace(namespaceId);
1998
- if (mountedRef.current) {
1999
- setNamespace(result);
2000
- }
2001
- } catch (err) {
2002
- const errorValue = toError(err);
2003
- if (mountedRef.current) {
2004
- setError(errorValue);
2005
- }
2006
- } finally {
2007
- if (mountedRef.current) {
2008
- setLoading(false);
2009
- }
2010
- }
2011
- }, [namespaceId, mero, mountedRef]);
2012
- react.useEffect(() => {
2013
- void refetch();
2014
- }, [refetch]);
2015
- return { namespace, loading, error, refetch };
1862
+ const { data, loading, error, refetch } = useAsyncResource(
1863
+ mero && namespaceId ? () => mero.admin.getNamespace(namespaceId) : null,
1864
+ null,
1865
+ [mero, namespaceId]
1866
+ );
1867
+ return { namespace: data, loading, error, refetch };
2016
1868
  }
2017
1869
  function useNamespaceIdentity(namespaceId) {
2018
1870
  const { mero } = useMero();
2019
- const [identity, setIdentity] = react.useState(null);
2020
- const [loading, setLoading] = react.useState(false);
2021
- const [error, setError] = react.useState(null);
2022
- const mountedRef = useMountedRef();
2023
- const refetch = react.useCallback(async () => {
2024
- if (!mero || !namespaceId) {
2025
- if (mountedRef.current) {
2026
- setIdentity(null);
2027
- setError(null);
2028
- setLoading(false);
2029
- }
2030
- return;
2031
- }
2032
- if (mountedRef.current) {
2033
- setLoading(true);
2034
- setError(null);
2035
- }
2036
- try {
2037
- const result = await mero.admin.getNamespaceIdentity(namespaceId);
2038
- if (mountedRef.current) {
2039
- setIdentity(result);
2040
- }
2041
- } catch (err) {
2042
- const errorValue = toError(err);
2043
- if (mountedRef.current) {
2044
- setError(errorValue);
2045
- }
2046
- } finally {
2047
- if (mountedRef.current) {
2048
- setLoading(false);
2049
- }
2050
- }
2051
- }, [namespaceId, mero, mountedRef]);
2052
- react.useEffect(() => {
2053
- void refetch();
2054
- }, [refetch]);
2055
- return { identity, loading, error, refetch };
1871
+ const { data, loading, error, refetch } = useAsyncResource(
1872
+ mero && namespaceId ? () => mero.admin.getNamespaceIdentity(namespaceId) : null,
1873
+ null,
1874
+ [mero, namespaceId]
1875
+ );
1876
+ return { identity: data, loading, error, refetch };
2056
1877
  }
2057
1878
  function useNamespacesForApplication(applicationId) {
2058
1879
  const { mero } = useMero();
2059
- const [namespaces, setNamespaces] = react.useState([]);
2060
- const [loading, setLoading] = react.useState(false);
2061
- const [error, setError] = react.useState(null);
2062
- const mountedRef = useMountedRef();
2063
- const refetch = react.useCallback(async () => {
2064
- if (!mero || !applicationId) {
2065
- if (mountedRef.current) {
2066
- setNamespaces([]);
2067
- setError(null);
2068
- setLoading(false);
2069
- }
2070
- return;
2071
- }
2072
- if (mountedRef.current) {
2073
- setLoading(true);
2074
- setError(null);
2075
- }
2076
- try {
2077
- const result = await mero.admin.listNamespacesForApplication(applicationId);
2078
- if (mountedRef.current) {
2079
- setNamespaces(result);
2080
- }
2081
- } catch (err) {
2082
- const errorValue = toError(err);
2083
- if (mountedRef.current) {
2084
- setError(errorValue);
2085
- }
2086
- } finally {
2087
- if (mountedRef.current) {
2088
- setLoading(false);
2089
- }
2090
- }
2091
- }, [applicationId, mero, mountedRef]);
2092
- react.useEffect(() => {
2093
- void refetch();
2094
- }, [refetch]);
2095
- return { namespaces, loading, error, refetch };
1880
+ const { data, loading, error, refetch } = useAsyncResource(
1881
+ mero && applicationId ? () => mero.admin.listNamespacesForApplication(applicationId) : null,
1882
+ [],
1883
+ [mero, applicationId]
1884
+ );
1885
+ return { namespaces: data, loading, error, refetch };
2096
1886
  }
2097
1887
  function useCreateNamespace() {
2098
1888
  const { mero } = useMero();
@@ -2156,43 +1946,12 @@ function useCreateGroupInNamespace() {
2156
1946
  }
2157
1947
  function useNamespaceGroups(namespaceId) {
2158
1948
  const { mero } = useMero();
2159
- const [groups, setGroups] = react.useState([]);
2160
- const [loading, setLoading] = react.useState(false);
2161
- const [error, setError] = react.useState(null);
2162
- const mountedRef = useMountedRef();
2163
- const refetch = react.useCallback(async () => {
2164
- if (!mero || !namespaceId) {
2165
- if (mountedRef.current) {
2166
- setGroups([]);
2167
- setError(null);
2168
- setLoading(false);
2169
- }
2170
- return;
2171
- }
2172
- if (mountedRef.current) {
2173
- setLoading(true);
2174
- setError(null);
2175
- }
2176
- try {
2177
- const result = await mero.admin.listNamespaceGroups(namespaceId);
2178
- if (mountedRef.current) {
2179
- setGroups(result);
2180
- }
2181
- } catch (err) {
2182
- const errorValue = toError(err);
2183
- if (mountedRef.current) {
2184
- setError(errorValue);
2185
- }
2186
- } finally {
2187
- if (mountedRef.current) {
2188
- setLoading(false);
2189
- }
2190
- }
2191
- }, [namespaceId, mero, mountedRef]);
2192
- react.useEffect(() => {
2193
- void refetch();
2194
- }, [refetch]);
2195
- return { groups, loading, error, refetch };
1949
+ const { data, loading, error, refetch } = useAsyncResource(
1950
+ mero && namespaceId ? () => mero.admin.listNamespaceGroups(namespaceId) : null,
1951
+ [],
1952
+ [mero, namespaceId]
1953
+ );
1954
+ return { groups: data, loading, error, refetch };
2196
1955
  }
2197
1956
  function useUpdateMemberRole() {
2198
1957
  const { mero } = useMero();
@@ -2232,83 +1991,21 @@ function useSetSubgroupVisibility() {
2232
1991
  }
2233
1992
  function useDefaultCapabilities(groupId) {
2234
1993
  const { mero } = useMero();
2235
- const [defaultCapabilities, setDefaultCapabilitiesState] = react.useState(null);
2236
- const [loading, setLoading] = react.useState(false);
2237
- const [error, setError] = react.useState(null);
2238
- const mountedRef = useMountedRef();
2239
- const refetch = react.useCallback(async () => {
2240
- if (!mero || !groupId) {
2241
- if (mountedRef.current) {
2242
- setDefaultCapabilitiesState(null);
2243
- setError(null);
2244
- setLoading(false);
2245
- }
2246
- return;
2247
- }
2248
- if (mountedRef.current) {
2249
- setLoading(true);
2250
- setError(null);
2251
- }
2252
- try {
2253
- const result = await mero.admin.getDefaultCapabilities(groupId);
2254
- if (mountedRef.current) {
2255
- setDefaultCapabilitiesState(result);
2256
- }
2257
- } catch (err) {
2258
- const errorValue = toError(err);
2259
- if (mountedRef.current) {
2260
- setError(errorValue);
2261
- }
2262
- } finally {
2263
- if (mountedRef.current) {
2264
- setLoading(false);
2265
- }
2266
- }
2267
- }, [groupId, mero, mountedRef]);
2268
- react.useEffect(() => {
2269
- void refetch();
2270
- }, [refetch]);
2271
- return { defaultCapabilities, loading, error, refetch };
1994
+ const { data, loading, error, refetch } = useAsyncResource(
1995
+ mero && groupId ? () => mero.admin.getDefaultCapabilities(groupId) : null,
1996
+ null,
1997
+ [mero, groupId]
1998
+ );
1999
+ return { defaultCapabilities: data, loading, error, refetch };
2272
2000
  }
2273
2001
  function useSubgroupVisibility(groupId) {
2274
2002
  const { mero } = useMero();
2275
- const [subgroupVisibility, setSubgroupVisibilityState] = react.useState(null);
2276
- const [loading, setLoading] = react.useState(false);
2277
- const [error, setError] = react.useState(null);
2278
- const mountedRef = useMountedRef();
2279
- const refetch = react.useCallback(async () => {
2280
- if (!mero || !groupId) {
2281
- if (mountedRef.current) {
2282
- setSubgroupVisibilityState(null);
2283
- setError(null);
2284
- setLoading(false);
2285
- }
2286
- return;
2287
- }
2288
- if (mountedRef.current) {
2289
- setLoading(true);
2290
- setError(null);
2291
- }
2292
- try {
2293
- const result = await mero.admin.getSubgroupVisibility(groupId);
2294
- if (mountedRef.current) {
2295
- setSubgroupVisibilityState(result);
2296
- }
2297
- } catch (err) {
2298
- const errorValue = toError(err);
2299
- if (mountedRef.current) {
2300
- setError(errorValue);
2301
- }
2302
- } finally {
2303
- if (mountedRef.current) {
2304
- setLoading(false);
2305
- }
2306
- }
2307
- }, [groupId, mero, mountedRef]);
2308
- react.useEffect(() => {
2309
- void refetch();
2310
- }, [refetch]);
2311
- return { subgroupVisibility, loading, error, refetch };
2003
+ const { data, loading, error, refetch } = useAsyncResource(
2004
+ mero && groupId ? () => mero.admin.getSubgroupVisibility(groupId) : null,
2005
+ null,
2006
+ [mero, groupId]
2007
+ );
2008
+ return { subgroupVisibility: data, loading, error, refetch };
2312
2009
  }
2313
2010
  function useSetTeeAdmissionPolicy() {
2314
2011
  const { mero } = useMero();
@@ -2372,43 +2069,12 @@ function useSetContextMetadata() {
2372
2069
  }
2373
2070
  function useGroupMetadata(groupId) {
2374
2071
  const { mero } = useMero();
2375
- const [metadata, setMetadata] = react.useState(null);
2376
- const [loading, setLoading] = react.useState(false);
2377
- const [error, setError] = react.useState(null);
2378
- const mountedRef = useMountedRef();
2379
- const refetch = react.useCallback(async () => {
2380
- if (!mero || !groupId) {
2381
- if (mountedRef.current) {
2382
- setMetadata(null);
2383
- setError(null);
2384
- setLoading(false);
2385
- }
2386
- return;
2387
- }
2388
- if (mountedRef.current) {
2389
- setLoading(true);
2390
- setError(null);
2391
- }
2392
- try {
2393
- const result = await mero.admin.getGroupMetadata(groupId);
2394
- if (mountedRef.current) {
2395
- setMetadata(result);
2396
- }
2397
- } catch (err) {
2398
- const errorValue = toError(err);
2399
- if (mountedRef.current) {
2400
- setError(errorValue);
2401
- }
2402
- } finally {
2403
- if (mountedRef.current) {
2404
- setLoading(false);
2405
- }
2406
- }
2407
- }, [groupId, mero, mountedRef]);
2408
- react.useEffect(() => {
2409
- void refetch();
2410
- }, [refetch]);
2411
- return { metadata, loading, error, refetch };
2072
+ const { data, loading, error, refetch } = useAsyncResource(
2073
+ mero && groupId ? () => mero.admin.getGroupMetadata(groupId) : null,
2074
+ null,
2075
+ [mero, groupId]
2076
+ );
2077
+ return { metadata: data, loading, error, refetch };
2412
2078
  }
2413
2079
  function useMemberMetadata(groupId, identity) {
2414
2080
  const { mero } = useMero();
@@ -2562,43 +2228,12 @@ function useReparentGroup() {
2562
2228
  }
2563
2229
  function useSubgroups(groupId) {
2564
2230
  const { mero } = useMero();
2565
- const [subgroups, setSubgroups] = react.useState([]);
2566
- const [loading, setLoading] = react.useState(false);
2567
- const [error, setError] = react.useState(null);
2568
- const mountedRef = useMountedRef();
2569
- const refetch = react.useCallback(async () => {
2570
- if (!mero || !groupId) {
2571
- if (mountedRef.current) {
2572
- setSubgroups([]);
2573
- setError(null);
2574
- setLoading(false);
2575
- }
2576
- return;
2577
- }
2578
- if (mountedRef.current) {
2579
- setLoading(true);
2580
- setError(null);
2581
- }
2582
- try {
2583
- const result = await mero.admin.listSubgroups(groupId);
2584
- if (mountedRef.current) {
2585
- setSubgroups(result);
2586
- }
2587
- } catch (err) {
2588
- const errorValue = toError(err);
2589
- if (mountedRef.current) {
2590
- setError(errorValue);
2591
- }
2592
- } finally {
2593
- if (mountedRef.current) {
2594
- setLoading(false);
2595
- }
2596
- }
2597
- }, [groupId, mero, mountedRef]);
2598
- react.useEffect(() => {
2599
- void refetch();
2600
- }, [refetch]);
2601
- return { subgroups, loading, error, refetch };
2231
+ const { data, loading, error, refetch } = useAsyncResource(
2232
+ mero && groupId ? () => mero.admin.listSubgroups(groupId) : null,
2233
+ [],
2234
+ [mero, groupId]
2235
+ );
2236
+ return { subgroups: data, loading, error, refetch };
2602
2237
  }
2603
2238
  function useDetachContextFromGroup() {
2604
2239
  const { mero } = useMero();