@calimero-network/mero-react 4.1.1 → 4.3.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
@@ -200,9 +200,18 @@ var isBrowser = typeof window !== "undefined";
200
200
  function getPermissionsForMode(mode) {
201
201
  switch (mode) {
202
202
  case "single-context" /* SingleContext */:
203
- return ["context:execute"];
203
+ return ["context:execute", "context:list", "application:list", "blob", "context:alias"];
204
204
  case "multi-context" /* MultiContext */:
205
- return ["context:create", "context:list", "context:execute"];
205
+ return [
206
+ "context:create",
207
+ "context:list",
208
+ "context:execute",
209
+ "application:list",
210
+ "namespace",
211
+ "group",
212
+ "blob",
213
+ "context:alias"
214
+ ];
206
215
  case "admin" /* Admin */:
207
216
  return ["admin"];
208
217
  default:
@@ -1369,6 +1378,49 @@ function useAsyncMutation() {
1369
1378
  );
1370
1379
  return { loading, error, run, setError };
1371
1380
  }
1381
+ function useAsyncResource(fetcher, initialValue, deps) {
1382
+ const mountedRef = useMountedRef();
1383
+ const [data, setData] = react.useState(initialValue);
1384
+ const [loading, setLoading] = react.useState(false);
1385
+ const [error, setError] = react.useState(null);
1386
+ const reqRef = react.useRef(0);
1387
+ const fetcherRef = react.useRef(fetcher);
1388
+ fetcherRef.current = fetcher;
1389
+ const initialRef = react.useRef(initialValue);
1390
+ const refetch = react.useCallback(async () => {
1391
+ const seq = ++reqRef.current;
1392
+ const fn = fetcherRef.current;
1393
+ if (!fn) {
1394
+ if (mountedRef.current && seq === reqRef.current) {
1395
+ setData(initialRef.current);
1396
+ setError(null);
1397
+ setLoading(false);
1398
+ }
1399
+ return;
1400
+ }
1401
+ if (mountedRef.current) {
1402
+ setLoading(true);
1403
+ setError(null);
1404
+ }
1405
+ try {
1406
+ const result = await fn();
1407
+ if (mountedRef.current && seq === reqRef.current) setData(result);
1408
+ } catch (err) {
1409
+ if (mountedRef.current && seq === reqRef.current) setError(toError(err));
1410
+ } finally {
1411
+ if (mountedRef.current && seq === reqRef.current) setLoading(false);
1412
+ }
1413
+ }, deps);
1414
+ react.useEffect(() => {
1415
+ reqRef.current += 1;
1416
+ setData(initialRef.current);
1417
+ setError(null);
1418
+ }, deps);
1419
+ react.useEffect(() => {
1420
+ void refetch();
1421
+ }, [refetch]);
1422
+ return { data, loading, error, refetch };
1423
+ }
1372
1424
  function sleep(ms) {
1373
1425
  return new Promise((resolve) => {
1374
1426
  setTimeout(resolve, ms);
@@ -1453,123 +1505,42 @@ function useSubscription(contextIds, callback) {
1453
1505
  }
1454
1506
  function useContexts(applicationId) {
1455
1507
  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 {
1508
+ const { data, loading, error, refetch } = useAsyncResource(
1509
+ mero ? async () => {
1467
1510
  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 };
1511
+ return mapApplicationContexts(response.contexts ?? []);
1512
+ } : null,
1513
+ [],
1514
+ [mero, applicationId]
1515
+ );
1516
+ return { contexts: data, loading, error, refetch };
1487
1517
  }
1488
1518
  function useApplicationContexts(applicationId) {
1489
1519
  return useContexts(applicationId);
1490
1520
  }
1491
1521
  function useGroupMembers(groupId) {
1492
1522
  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 };
1523
+ const { data, loading, error, refetch } = useAsyncResource(
1524
+ mero && groupId ? () => mero.admin.listGroupMembers(groupId) : null,
1525
+ null,
1526
+ [mero, groupId]
1527
+ );
1528
+ return {
1529
+ members: data?.members ?? [],
1530
+ selfIdentity: data?.selfIdentity ?? null,
1531
+ loading,
1532
+ error,
1533
+ refetch
1534
+ };
1533
1535
  }
1534
1536
  function useGroupContexts(groupId) {
1535
1537
  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 };
1538
+ const { data, loading, error, refetch } = useAsyncResource(
1539
+ mero && groupId ? () => mero.admin.listGroupContexts(groupId) : null,
1540
+ [],
1541
+ [mero, groupId]
1542
+ );
1543
+ return { contexts: data, loading, error, refetch };
1573
1544
  }
1574
1545
  function useGroupInvitations() {
1575
1546
  const { mero } = useMero();
@@ -1605,9 +1576,11 @@ function useGroupCapabilities(groupId, memberId) {
1605
1576
  const [loading, setLoading] = react.useState(false);
1606
1577
  const [error, setError] = react.useState(null);
1607
1578
  const mountedRef = useMountedRef();
1579
+ const reqRef = react.useRef(0);
1608
1580
  const refetch = react.useCallback(async () => {
1581
+ const seq = ++reqRef.current;
1609
1582
  if (!mero || !groupId || !memberId) {
1610
- if (mountedRef.current) {
1583
+ if (mountedRef.current && seq === reqRef.current) {
1611
1584
  setCapabilitiesState(null);
1612
1585
  setError(null);
1613
1586
  setLoading(false);
@@ -1620,22 +1593,27 @@ function useGroupCapabilities(groupId, memberId) {
1620
1593
  }
1621
1594
  try {
1622
1595
  const response = await mero.admin.getMemberCapabilities(groupId, memberId);
1623
- if (mountedRef.current) {
1596
+ if (mountedRef.current && seq === reqRef.current) {
1624
1597
  setCapabilitiesState(response.capabilities);
1625
1598
  }
1626
1599
  return response.capabilities;
1627
1600
  } catch (err) {
1628
1601
  const errorValue = toError(err);
1629
- if (mountedRef.current) {
1602
+ if (mountedRef.current && seq === reqRef.current) {
1630
1603
  setError(errorValue);
1631
1604
  }
1632
1605
  return null;
1633
1606
  } finally {
1634
- if (mountedRef.current) {
1607
+ if (mountedRef.current && seq === reqRef.current) {
1635
1608
  setLoading(false);
1636
1609
  }
1637
1610
  }
1638
1611
  }, [groupId, memberId, mero, mountedRef]);
1612
+ react.useEffect(() => {
1613
+ reqRef.current += 1;
1614
+ setCapabilitiesState(null);
1615
+ setError(null);
1616
+ }, [groupId, memberId]);
1639
1617
  react.useEffect(() => {
1640
1618
  void refetch();
1641
1619
  }, [refetch]);
@@ -1815,83 +1793,21 @@ function useJoinSubgroupInheritance() {
1815
1793
  }
1816
1794
  function useContextGroup(contextId) {
1817
1795
  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 };
1796
+ const { data, loading, error, refetch } = useAsyncResource(
1797
+ mero && contextId ? () => mero.admin.getContextGroup(contextId) : null,
1798
+ null,
1799
+ [mero, contextId]
1800
+ );
1801
+ return { groupId: data, loading, error, refetch };
1855
1802
  }
1856
1803
  function useGroupInfo(groupId) {
1857
1804
  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 };
1805
+ const { data, loading, error, refetch } = useAsyncResource(
1806
+ mero && groupId ? () => mero.admin.getGroupInfo(groupId) : null,
1807
+ null,
1808
+ [mero, groupId]
1809
+ );
1810
+ return { groupInfo: data, loading, error, refetch };
1895
1811
  }
1896
1812
  function useDeleteGroup() {
1897
1813
  const { mero } = useMero();
@@ -1943,156 +1859,39 @@ function useRemoveGroupMembers() {
1943
1859
  }
1944
1860
  function useNamespaces() {
1945
1861
  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 };
1862
+ const { data, loading, error, refetch } = useAsyncResource(
1863
+ mero ? () => mero.admin.listNamespaces() : null,
1864
+ [],
1865
+ [mero]
1866
+ );
1867
+ return { namespaces: data, loading, error, refetch };
1976
1868
  }
1977
1869
  function useNamespace(namespaceId) {
1978
1870
  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 };
1871
+ const { data, loading, error, refetch } = useAsyncResource(
1872
+ mero && namespaceId ? () => mero.admin.getNamespace(namespaceId) : null,
1873
+ null,
1874
+ [mero, namespaceId]
1875
+ );
1876
+ return { namespace: data, loading, error, refetch };
2016
1877
  }
2017
1878
  function useNamespaceIdentity(namespaceId) {
2018
1879
  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 };
1880
+ const { data, loading, error, refetch } = useAsyncResource(
1881
+ mero && namespaceId ? () => mero.admin.getNamespaceIdentity(namespaceId) : null,
1882
+ null,
1883
+ [mero, namespaceId]
1884
+ );
1885
+ return { identity: data, loading, error, refetch };
2056
1886
  }
2057
1887
  function useNamespacesForApplication(applicationId) {
2058
1888
  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 };
1889
+ const { data, loading, error, refetch } = useAsyncResource(
1890
+ mero && applicationId ? () => mero.admin.listNamespacesForApplication(applicationId) : null,
1891
+ [],
1892
+ [mero, applicationId]
1893
+ );
1894
+ return { namespaces: data, loading, error, refetch };
2096
1895
  }
2097
1896
  function useCreateNamespace() {
2098
1897
  const { mero } = useMero();
@@ -2156,43 +1955,12 @@ function useCreateGroupInNamespace() {
2156
1955
  }
2157
1956
  function useNamespaceGroups(namespaceId) {
2158
1957
  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 };
1958
+ const { data, loading, error, refetch } = useAsyncResource(
1959
+ mero && namespaceId ? () => mero.admin.listNamespaceGroups(namespaceId) : null,
1960
+ [],
1961
+ [mero, namespaceId]
1962
+ );
1963
+ return { groups: data, loading, error, refetch };
2196
1964
  }
2197
1965
  function useUpdateMemberRole() {
2198
1966
  const { mero } = useMero();
@@ -2232,83 +2000,21 @@ function useSetSubgroupVisibility() {
2232
2000
  }
2233
2001
  function useDefaultCapabilities(groupId) {
2234
2002
  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 };
2003
+ const { data, loading, error, refetch } = useAsyncResource(
2004
+ mero && groupId ? () => mero.admin.getDefaultCapabilities(groupId) : null,
2005
+ null,
2006
+ [mero, groupId]
2007
+ );
2008
+ return { defaultCapabilities: data, loading, error, refetch };
2272
2009
  }
2273
2010
  function useSubgroupVisibility(groupId) {
2274
2011
  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 };
2012
+ const { data, loading, error, refetch } = useAsyncResource(
2013
+ mero && groupId ? () => mero.admin.getSubgroupVisibility(groupId) : null,
2014
+ null,
2015
+ [mero, groupId]
2016
+ );
2017
+ return { subgroupVisibility: data, loading, error, refetch };
2312
2018
  }
2313
2019
  function useSetTeeAdmissionPolicy() {
2314
2020
  const { mero } = useMero();
@@ -2372,43 +2078,12 @@ function useSetContextMetadata() {
2372
2078
  }
2373
2079
  function useGroupMetadata(groupId) {
2374
2080
  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 };
2081
+ const { data, loading, error, refetch } = useAsyncResource(
2082
+ mero && groupId ? () => mero.admin.getGroupMetadata(groupId) : null,
2083
+ null,
2084
+ [mero, groupId]
2085
+ );
2086
+ return { metadata: data, loading, error, refetch };
2412
2087
  }
2413
2088
  function useMemberMetadata(groupId, identity) {
2414
2089
  const { mero } = useMero();
@@ -2562,43 +2237,12 @@ function useReparentGroup() {
2562
2237
  }
2563
2238
  function useSubgroups(groupId) {
2564
2239
  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 };
2240
+ const { data, loading, error, refetch } = useAsyncResource(
2241
+ mero && groupId ? () => mero.admin.listSubgroups(groupId) : null,
2242
+ [],
2243
+ [mero, groupId]
2244
+ );
2245
+ return { subgroups: data, loading, error, refetch };
2602
2246
  }
2603
2247
  function useDetachContextFromGroup() {
2604
2248
  const { mero } = useMero();