@ai4b-team/fsaos-gateway-sdk 3.34.2 → 3.35.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/iife/gateway.js +5 -5
- package/dist/iife/gateway.js.map +4 -4
- package/dist/iife/ui.js +1 -1
- package/dist/index.cjs +60 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +89 -2
- package/dist/index.d.ts +89 -2
- package/dist/index.js +60 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1085,6 +1085,10 @@ interface ItemsFilter {
|
|
|
1085
1085
|
type?: string;
|
|
1086
1086
|
/** Scope path boundary. Defaults to session scope. */
|
|
1087
1087
|
scope?: string;
|
|
1088
|
+
/** Explicit mounted Space UUIDs, filtered by the kernel before pagination.
|
|
1089
|
+
* [] returns no work. Omitted preserves legacy scope behavior. This is a
|
|
1090
|
+
* read selection, never a write target or permission grant. */
|
|
1091
|
+
spaceIds?: string[];
|
|
1088
1092
|
/** Direct parent_id filter. */
|
|
1089
1093
|
parent_id?: string;
|
|
1090
1094
|
/** Name ILIKE filter (partial match). */
|
|
@@ -1131,7 +1135,7 @@ declare function isListableItemsFilter(filter: ItemsFilter | null | undefined):
|
|
|
1131
1135
|
* icon, ...) are ignored. `extra` adds what the screen owns: scope, page size.
|
|
1132
1136
|
* Returns null when the stored filter names nothing to list.
|
|
1133
1137
|
*/
|
|
1134
|
-
declare function itemsFilterFromQueryFilter(typeData: Record<string, unknown> | null | undefined, extra?: Pick<ItemsFilter, 'scope' | 'limit' | 'name' | 'parent_id'>): ItemsFilter | null;
|
|
1138
|
+
declare function itemsFilterFromQueryFilter(typeData: Record<string, unknown> | null | undefined, extra?: Pick<ItemsFilter, 'scope' | 'spaceIds' | 'limit' | 'name' | 'parent_id'>): ItemsFilter | null;
|
|
1135
1139
|
/**
|
|
1136
1140
|
* Fetch items with structured filters: one type, or OR-groups across types.
|
|
1137
1141
|
* Calls kernel_query (gateway 'query' method). The kernel filters before it
|
|
@@ -1654,7 +1658,88 @@ declare function useSearch(query: string | undefined | null, itemTypes?: string[
|
|
|
1654
1658
|
/** Multi-signal search (exact + trigram + keyword + semantic vector) via kernel resolve. */
|
|
1655
1659
|
declare function useResolve(params: ResolveParams | null | undefined): _tanstack_react_query.UseQueryResult<ResolveResponse, Error>;
|
|
1656
1660
|
/** Fetch items with structured filters: one type, or OR-groups across types. */
|
|
1657
|
-
declare function useItems(filter: ItemsFilter | null | undefined): _tanstack_react_query.
|
|
1661
|
+
declare function useItems(filter: ItemsFilter | null | undefined): _tanstack_react_query.QueryObserverRefetchErrorResult<VFSItem[], Error> | _tanstack_react_query.QueryObserverSuccessResult<VFSItem[], Error> | _tanstack_react_query.QueryObserverLoadingErrorResult<VFSItem[], Error> | _tanstack_react_query.QueryObserverPendingResult<VFSItem[], Error> | _tanstack_react_query.QueryObserverPlaceholderResult<VFSItem[], Error> | {
|
|
1662
|
+
data: undefined;
|
|
1663
|
+
error: Error;
|
|
1664
|
+
isError: true;
|
|
1665
|
+
isPending: false;
|
|
1666
|
+
isLoading: false;
|
|
1667
|
+
isLoadingError: false;
|
|
1668
|
+
isRefetchError: true;
|
|
1669
|
+
isSuccess: false;
|
|
1670
|
+
isPlaceholderData: false;
|
|
1671
|
+
status: "error";
|
|
1672
|
+
dataUpdatedAt: number;
|
|
1673
|
+
errorUpdatedAt: number;
|
|
1674
|
+
failureCount: number;
|
|
1675
|
+
failureReason: Error | null;
|
|
1676
|
+
errorUpdateCount: number;
|
|
1677
|
+
isFetched: boolean;
|
|
1678
|
+
isFetchedAfterMount: boolean;
|
|
1679
|
+
isFetching: boolean;
|
|
1680
|
+
isInitialLoading: boolean;
|
|
1681
|
+
isPaused: boolean;
|
|
1682
|
+
isRefetching: boolean;
|
|
1683
|
+
isStale: boolean;
|
|
1684
|
+
isEnabled: boolean;
|
|
1685
|
+
refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<VFSItem[], Error>>;
|
|
1686
|
+
fetchStatus: _tanstack_react_query.FetchStatus;
|
|
1687
|
+
promise: Promise<VFSItem[]>;
|
|
1688
|
+
} | {
|
|
1689
|
+
data: undefined;
|
|
1690
|
+
error: null;
|
|
1691
|
+
isError: false;
|
|
1692
|
+
isPending: false;
|
|
1693
|
+
isLoading: false;
|
|
1694
|
+
isLoadingError: false;
|
|
1695
|
+
isRefetchError: false;
|
|
1696
|
+
isSuccess: true;
|
|
1697
|
+
isPlaceholderData: false;
|
|
1698
|
+
status: "success";
|
|
1699
|
+
dataUpdatedAt: number;
|
|
1700
|
+
errorUpdatedAt: number;
|
|
1701
|
+
failureCount: number;
|
|
1702
|
+
failureReason: Error | null;
|
|
1703
|
+
errorUpdateCount: number;
|
|
1704
|
+
isFetched: boolean;
|
|
1705
|
+
isFetchedAfterMount: boolean;
|
|
1706
|
+
isFetching: boolean;
|
|
1707
|
+
isInitialLoading: boolean;
|
|
1708
|
+
isPaused: boolean;
|
|
1709
|
+
isRefetching: boolean;
|
|
1710
|
+
isStale: boolean;
|
|
1711
|
+
isEnabled: boolean;
|
|
1712
|
+
refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<VFSItem[], Error>>;
|
|
1713
|
+
fetchStatus: _tanstack_react_query.FetchStatus;
|
|
1714
|
+
promise: Promise<VFSItem[]>;
|
|
1715
|
+
} | {
|
|
1716
|
+
data: undefined;
|
|
1717
|
+
isError: false;
|
|
1718
|
+
error: null;
|
|
1719
|
+
isPending: false;
|
|
1720
|
+
isLoading: false;
|
|
1721
|
+
isLoadingError: false;
|
|
1722
|
+
isRefetchError: false;
|
|
1723
|
+
isSuccess: true;
|
|
1724
|
+
isPlaceholderData: true;
|
|
1725
|
+
status: "success";
|
|
1726
|
+
dataUpdatedAt: number;
|
|
1727
|
+
errorUpdatedAt: number;
|
|
1728
|
+
failureCount: number;
|
|
1729
|
+
failureReason: Error | null;
|
|
1730
|
+
errorUpdateCount: number;
|
|
1731
|
+
isFetched: boolean;
|
|
1732
|
+
isFetchedAfterMount: boolean;
|
|
1733
|
+
isFetching: boolean;
|
|
1734
|
+
isInitialLoading: boolean;
|
|
1735
|
+
isPaused: boolean;
|
|
1736
|
+
isRefetching: boolean;
|
|
1737
|
+
isStale: boolean;
|
|
1738
|
+
isEnabled: boolean;
|
|
1739
|
+
refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<VFSItem[], Error>>;
|
|
1740
|
+
fetchStatus: _tanstack_react_query.FetchStatus;
|
|
1741
|
+
promise: Promise<VFSItem[]>;
|
|
1742
|
+
};
|
|
1658
1743
|
interface InfiniteItemsOptions {
|
|
1659
1744
|
/** Keep this cached listing fresh through the SDK's existing realtime transport. No polling. Defaults to false. */
|
|
1660
1745
|
realtime?: boolean;
|
|
@@ -1967,6 +2052,8 @@ declare function useAccounts(): AccountsState;
|
|
|
1967
2052
|
/** The working set (mounts) as reactive state, plus mount/unmount verbs. */
|
|
1968
2053
|
declare function useMounts(): {
|
|
1969
2054
|
mounts: MountRef[];
|
|
2055
|
+
selectedSpaces: MountRef[];
|
|
2056
|
+
readSpaceIds: string[];
|
|
1970
2057
|
homeAnchor: MountRef | null;
|
|
1971
2058
|
anchor: MountRef | null;
|
|
1972
2059
|
setAnchor: typeof selectMount;
|
package/dist/index.d.ts
CHANGED
|
@@ -1085,6 +1085,10 @@ interface ItemsFilter {
|
|
|
1085
1085
|
type?: string;
|
|
1086
1086
|
/** Scope path boundary. Defaults to session scope. */
|
|
1087
1087
|
scope?: string;
|
|
1088
|
+
/** Explicit mounted Space UUIDs, filtered by the kernel before pagination.
|
|
1089
|
+
* [] returns no work. Omitted preserves legacy scope behavior. This is a
|
|
1090
|
+
* read selection, never a write target or permission grant. */
|
|
1091
|
+
spaceIds?: string[];
|
|
1088
1092
|
/** Direct parent_id filter. */
|
|
1089
1093
|
parent_id?: string;
|
|
1090
1094
|
/** Name ILIKE filter (partial match). */
|
|
@@ -1131,7 +1135,7 @@ declare function isListableItemsFilter(filter: ItemsFilter | null | undefined):
|
|
|
1131
1135
|
* icon, ...) are ignored. `extra` adds what the screen owns: scope, page size.
|
|
1132
1136
|
* Returns null when the stored filter names nothing to list.
|
|
1133
1137
|
*/
|
|
1134
|
-
declare function itemsFilterFromQueryFilter(typeData: Record<string, unknown> | null | undefined, extra?: Pick<ItemsFilter, 'scope' | 'limit' | 'name' | 'parent_id'>): ItemsFilter | null;
|
|
1138
|
+
declare function itemsFilterFromQueryFilter(typeData: Record<string, unknown> | null | undefined, extra?: Pick<ItemsFilter, 'scope' | 'spaceIds' | 'limit' | 'name' | 'parent_id'>): ItemsFilter | null;
|
|
1135
1139
|
/**
|
|
1136
1140
|
* Fetch items with structured filters: one type, or OR-groups across types.
|
|
1137
1141
|
* Calls kernel_query (gateway 'query' method). The kernel filters before it
|
|
@@ -1654,7 +1658,88 @@ declare function useSearch(query: string | undefined | null, itemTypes?: string[
|
|
|
1654
1658
|
/** Multi-signal search (exact + trigram + keyword + semantic vector) via kernel resolve. */
|
|
1655
1659
|
declare function useResolve(params: ResolveParams | null | undefined): _tanstack_react_query.UseQueryResult<ResolveResponse, Error>;
|
|
1656
1660
|
/** Fetch items with structured filters: one type, or OR-groups across types. */
|
|
1657
|
-
declare function useItems(filter: ItemsFilter | null | undefined): _tanstack_react_query.
|
|
1661
|
+
declare function useItems(filter: ItemsFilter | null | undefined): _tanstack_react_query.QueryObserverRefetchErrorResult<VFSItem[], Error> | _tanstack_react_query.QueryObserverSuccessResult<VFSItem[], Error> | _tanstack_react_query.QueryObserverLoadingErrorResult<VFSItem[], Error> | _tanstack_react_query.QueryObserverPendingResult<VFSItem[], Error> | _tanstack_react_query.QueryObserverPlaceholderResult<VFSItem[], Error> | {
|
|
1662
|
+
data: undefined;
|
|
1663
|
+
error: Error;
|
|
1664
|
+
isError: true;
|
|
1665
|
+
isPending: false;
|
|
1666
|
+
isLoading: false;
|
|
1667
|
+
isLoadingError: false;
|
|
1668
|
+
isRefetchError: true;
|
|
1669
|
+
isSuccess: false;
|
|
1670
|
+
isPlaceholderData: false;
|
|
1671
|
+
status: "error";
|
|
1672
|
+
dataUpdatedAt: number;
|
|
1673
|
+
errorUpdatedAt: number;
|
|
1674
|
+
failureCount: number;
|
|
1675
|
+
failureReason: Error | null;
|
|
1676
|
+
errorUpdateCount: number;
|
|
1677
|
+
isFetched: boolean;
|
|
1678
|
+
isFetchedAfterMount: boolean;
|
|
1679
|
+
isFetching: boolean;
|
|
1680
|
+
isInitialLoading: boolean;
|
|
1681
|
+
isPaused: boolean;
|
|
1682
|
+
isRefetching: boolean;
|
|
1683
|
+
isStale: boolean;
|
|
1684
|
+
isEnabled: boolean;
|
|
1685
|
+
refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<VFSItem[], Error>>;
|
|
1686
|
+
fetchStatus: _tanstack_react_query.FetchStatus;
|
|
1687
|
+
promise: Promise<VFSItem[]>;
|
|
1688
|
+
} | {
|
|
1689
|
+
data: undefined;
|
|
1690
|
+
error: null;
|
|
1691
|
+
isError: false;
|
|
1692
|
+
isPending: false;
|
|
1693
|
+
isLoading: false;
|
|
1694
|
+
isLoadingError: false;
|
|
1695
|
+
isRefetchError: false;
|
|
1696
|
+
isSuccess: true;
|
|
1697
|
+
isPlaceholderData: false;
|
|
1698
|
+
status: "success";
|
|
1699
|
+
dataUpdatedAt: number;
|
|
1700
|
+
errorUpdatedAt: number;
|
|
1701
|
+
failureCount: number;
|
|
1702
|
+
failureReason: Error | null;
|
|
1703
|
+
errorUpdateCount: number;
|
|
1704
|
+
isFetched: boolean;
|
|
1705
|
+
isFetchedAfterMount: boolean;
|
|
1706
|
+
isFetching: boolean;
|
|
1707
|
+
isInitialLoading: boolean;
|
|
1708
|
+
isPaused: boolean;
|
|
1709
|
+
isRefetching: boolean;
|
|
1710
|
+
isStale: boolean;
|
|
1711
|
+
isEnabled: boolean;
|
|
1712
|
+
refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<VFSItem[], Error>>;
|
|
1713
|
+
fetchStatus: _tanstack_react_query.FetchStatus;
|
|
1714
|
+
promise: Promise<VFSItem[]>;
|
|
1715
|
+
} | {
|
|
1716
|
+
data: undefined;
|
|
1717
|
+
isError: false;
|
|
1718
|
+
error: null;
|
|
1719
|
+
isPending: false;
|
|
1720
|
+
isLoading: false;
|
|
1721
|
+
isLoadingError: false;
|
|
1722
|
+
isRefetchError: false;
|
|
1723
|
+
isSuccess: true;
|
|
1724
|
+
isPlaceholderData: true;
|
|
1725
|
+
status: "success";
|
|
1726
|
+
dataUpdatedAt: number;
|
|
1727
|
+
errorUpdatedAt: number;
|
|
1728
|
+
failureCount: number;
|
|
1729
|
+
failureReason: Error | null;
|
|
1730
|
+
errorUpdateCount: number;
|
|
1731
|
+
isFetched: boolean;
|
|
1732
|
+
isFetchedAfterMount: boolean;
|
|
1733
|
+
isFetching: boolean;
|
|
1734
|
+
isInitialLoading: boolean;
|
|
1735
|
+
isPaused: boolean;
|
|
1736
|
+
isRefetching: boolean;
|
|
1737
|
+
isStale: boolean;
|
|
1738
|
+
isEnabled: boolean;
|
|
1739
|
+
refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<VFSItem[], Error>>;
|
|
1740
|
+
fetchStatus: _tanstack_react_query.FetchStatus;
|
|
1741
|
+
promise: Promise<VFSItem[]>;
|
|
1742
|
+
};
|
|
1658
1743
|
interface InfiniteItemsOptions {
|
|
1659
1744
|
/** Keep this cached listing fresh through the SDK's existing realtime transport. No polling. Defaults to false. */
|
|
1660
1745
|
realtime?: boolean;
|
|
@@ -1967,6 +2052,8 @@ declare function useAccounts(): AccountsState;
|
|
|
1967
2052
|
/** The working set (mounts) as reactive state, plus mount/unmount verbs. */
|
|
1968
2053
|
declare function useMounts(): {
|
|
1969
2054
|
mounts: MountRef[];
|
|
2055
|
+
selectedSpaces: MountRef[];
|
|
2056
|
+
readSpaceIds: string[];
|
|
1970
2057
|
homeAnchor: MountRef | null;
|
|
1971
2058
|
anchor: MountRef | null;
|
|
1972
2059
|
setAnchor: typeof selectMount;
|
package/dist/index.js
CHANGED
|
@@ -757,6 +757,10 @@ function listingTypes(filter) {
|
|
|
757
757
|
}
|
|
758
758
|
function affectsListing(query, filter, event) {
|
|
759
759
|
if (containsChangedItem(query, event)) return true;
|
|
760
|
+
if (filter.spaceIds !== void 0) {
|
|
761
|
+
if (!filter.spaceIds.length) return false;
|
|
762
|
+
if (event.space_item_id !== void 0 && !filter.spaceIds.includes(event.space_item_id) && !filter.spaceIds.includes(event.old_space_item_id)) return false;
|
|
763
|
+
}
|
|
760
764
|
const scope = filter.scope;
|
|
761
765
|
const scoped = typeof scope === "string" && scope !== "__unscoped__";
|
|
762
766
|
const hasPath = typeof event.path === "string" || typeof event.old_path === "string";
|
|
@@ -800,6 +804,29 @@ function clearInfiniteItemsRefreshes(client2) {
|
|
|
800
804
|
pending2.delete(client2);
|
|
801
805
|
}
|
|
802
806
|
|
|
807
|
+
// src/items-selection.ts
|
|
808
|
+
var SelectedSpaceContractError = class extends Error {
|
|
809
|
+
constructor() {
|
|
810
|
+
super("The server did not confirm the selected-Space listing contract");
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
function assertItemsSelection(requested, returned) {
|
|
814
|
+
if (!Array.isArray(returned) || returned.some((id) => typeof id !== "string") || JSON.stringify([...new Set(returned)].sort()) !== JSON.stringify(requested)) {
|
|
815
|
+
throw new SelectedSpaceContractError();
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
function normalizeItemsSelection(filter) {
|
|
819
|
+
if (!filter || filter.spaceIds === void 0) return filter;
|
|
820
|
+
return {
|
|
821
|
+
...filter,
|
|
822
|
+
spaceIds: [...new Set(filter.spaceIds.map((id) => id.toLowerCase()))].sort(),
|
|
823
|
+
...filter.limit !== void 0 ? { limit: Math.max(1, Math.min(filter.limit, 500)) } : {}
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
function unavailableItemsSelection(error) {
|
|
827
|
+
return error instanceof SelectedSpaceContractError || error instanceof EnforcementDeniedError || error instanceof GatewayRequestError && (error.payload?.error === "SPACE_SELECTION_UNAVAILABLE" || error.payload?.error === "QUERY_PARAMS_INVALID" || error.status === 401 || error.status === 403);
|
|
828
|
+
}
|
|
829
|
+
|
|
803
830
|
// src/vfs-keys.ts
|
|
804
831
|
function sk() {
|
|
805
832
|
return getScope() ?? "__unscoped__";
|
|
@@ -822,7 +849,7 @@ var vfsKeys = {
|
|
|
822
849
|
/** Search results (scope-aware — search is scoped). */
|
|
823
850
|
search: (query, types) => ["vfs", sk(), "search", query, ...types ?? []],
|
|
824
851
|
/** Items query (type-based listing with filters, scope-aware). */
|
|
825
|
-
items: (type, filters) => ["vfs", sk(), "items", type, JSON.stringify(filters ?? {})],
|
|
852
|
+
items: (type, filters) => ["vfs", sk(), "items", type, JSON.stringify(normalizeItemsSelection(filters ?? {}))],
|
|
826
853
|
/** All items queries for current scope (for broad invalidation). */
|
|
827
854
|
allItems: () => ["vfs", sk(), "items"],
|
|
828
855
|
/** Recursive tree at a path + depth (scope-aware). */
|
|
@@ -1712,12 +1739,15 @@ function itemsFilterFromQueryFilter(typeData, extra = {}) {
|
|
|
1712
1739
|
return { ...filter, ...extra };
|
|
1713
1740
|
}
|
|
1714
1741
|
async function fetchItems(filter, options = {}) {
|
|
1742
|
+
filter = normalizeItemsSelection(filter);
|
|
1743
|
+
if (filter.spaceIds?.length === 0) return { items: [], total_hint: 0 };
|
|
1715
1744
|
const params = {};
|
|
1716
1745
|
if (filter.type) params.item_type = filter.type;
|
|
1717
1746
|
if (filter.scope) {
|
|
1718
1747
|
params.scope_path = filter.scope;
|
|
1719
1748
|
}
|
|
1720
1749
|
const filters = {};
|
|
1750
|
+
if (filter.spaceIds !== void 0) filters.space_ids = filter.spaceIds;
|
|
1721
1751
|
if (filter.name) filters.name = filter.name;
|
|
1722
1752
|
if (filter.tag) filters.tag = filter.tag;
|
|
1723
1753
|
if (filter.parent_id) filters.parent_id = filter.parent_id;
|
|
@@ -1744,6 +1774,9 @@ async function fetchItems(filter, options = {}) {
|
|
|
1744
1774
|
}
|
|
1745
1775
|
try {
|
|
1746
1776
|
const response = await gatewayCall("query", params);
|
|
1777
|
+
if (filter.spaceIds !== void 0) {
|
|
1778
|
+
assertItemsSelection(filter.spaceIds, response.selected_space_ids ?? response.content?.selected_space_ids);
|
|
1779
|
+
}
|
|
1747
1780
|
const items = extractItems(response);
|
|
1748
1781
|
for (const item of items) {
|
|
1749
1782
|
getQueryClient().setQueryData(vfsKeys.item(item.path), item);
|
|
@@ -1751,7 +1784,7 @@ async function fetchItems(filter, options = {}) {
|
|
|
1751
1784
|
return { items, total_hint: response.total ?? response.content?.total ?? items.length };
|
|
1752
1785
|
} catch (err) {
|
|
1753
1786
|
console.error(`[gateway] Failed to fetch items of type ${filter.type ?? "(any_of)"}:`, err);
|
|
1754
|
-
if (options.throwOnError) throw err;
|
|
1787
|
+
if (options.throwOnError || filter.spaceIds !== void 0) throw err;
|
|
1755
1788
|
return { items: [], total_hint: 0 };
|
|
1756
1789
|
}
|
|
1757
1790
|
}
|
|
@@ -2365,22 +2398,28 @@ function useResolve(params) {
|
|
|
2365
2398
|
}
|
|
2366
2399
|
function useItems(filter) {
|
|
2367
2400
|
useScopeKey();
|
|
2368
|
-
const
|
|
2369
|
-
|
|
2401
|
+
const selected = normalizeItemsSelection(filter);
|
|
2402
|
+
const stableFilter = useMemo(() => selected, [JSON.stringify(selected)]);
|
|
2403
|
+
const query = useQuery({
|
|
2370
2404
|
queryKey: vfsKeys.items(
|
|
2371
2405
|
stableFilter?.type ?? "",
|
|
2372
2406
|
stableFilter
|
|
2373
2407
|
),
|
|
2374
2408
|
queryFn: () => fetchItems(stableFilter),
|
|
2375
2409
|
enabled: isListableItemsFilter(stableFilter),
|
|
2410
|
+
...stableFilter?.spaceIds !== void 0 ? {
|
|
2411
|
+
retry: (attempt, error) => !unavailableItemsSelection(error) && attempt < 1
|
|
2412
|
+
} : {},
|
|
2376
2413
|
select: (result) => result.items
|
|
2377
2414
|
});
|
|
2415
|
+
return stableFilter?.spaceIds !== void 0 && unavailableItemsSelection(query.error) ? { ...query, data: void 0 } : query;
|
|
2378
2416
|
}
|
|
2379
2417
|
function useInfiniteItems(filter, options = {}) {
|
|
2380
2418
|
const scopeKey = useScopeKey();
|
|
2381
2419
|
const { realtime = false } = options;
|
|
2382
|
-
const
|
|
2383
|
-
const
|
|
2420
|
+
const selected = normalizeItemsSelection(filter);
|
|
2421
|
+
const PAGE_SIZE = selected?.limit ?? 20;
|
|
2422
|
+
const stableFilter = useMemo(() => selected, [JSON.stringify(selected)]);
|
|
2384
2423
|
const stableKey = useMemo(() => ["vfs", getScope() ?? "__unscoped__", "infinite-items", stableFilter?.type ?? "", JSON.stringify(stableFilter ?? {})], [scopeKey, stableFilter]);
|
|
2385
2424
|
const query = useInfiniteQuery({
|
|
2386
2425
|
queryKey: stableKey,
|
|
@@ -2393,16 +2432,21 @@ function useInfiniteItems(filter, options = {}) {
|
|
|
2393
2432
|
},
|
|
2394
2433
|
initialPageParam: 0,
|
|
2395
2434
|
getNextPageParam: (lastPage, _allPages, lastPageParam) => {
|
|
2435
|
+
if (stableFilter?.spaceIds !== void 0 && lastPage.total_hint !== void 0 && lastPageParam + lastPage.items.length >= lastPage.total_hint) return void 0;
|
|
2396
2436
|
if (lastPage.items.length < PAGE_SIZE) return void 0;
|
|
2397
2437
|
return lastPageParam + lastPage.items.length;
|
|
2398
2438
|
},
|
|
2399
2439
|
enabled: isListableItemsFilter(stableFilter),
|
|
2440
|
+
...stableFilter?.spaceIds !== void 0 ? {
|
|
2441
|
+
retry: (attempt, error) => !unavailableItemsSelection(error) && attempt < 1
|
|
2442
|
+
} : {},
|
|
2400
2443
|
// Realtime marks the cache stale only on relevant changes or reconnect.
|
|
2401
2444
|
// Expanding a channel or handing it to another observer reuses its pages.
|
|
2402
2445
|
staleTime: realtime ? Infinity : void 0,
|
|
2403
2446
|
meta: realtime && stableFilter ? { infiniteItemsRealtime: { filter: stableFilter } } : {}
|
|
2404
2447
|
});
|
|
2405
2448
|
const allItems = useMemo(() => {
|
|
2449
|
+
if (stableFilter?.spaceIds !== void 0 && unavailableItemsSelection(query.error)) return [];
|
|
2406
2450
|
if (!query.data?.pages) return [];
|
|
2407
2451
|
const seen = /* @__PURE__ */ new Set();
|
|
2408
2452
|
const flat = [];
|
|
@@ -2415,17 +2459,18 @@ function useInfiniteItems(filter, options = {}) {
|
|
|
2415
2459
|
}
|
|
2416
2460
|
}
|
|
2417
2461
|
return flat;
|
|
2418
|
-
}, [query.data?.pages]);
|
|
2462
|
+
}, [query.data?.pages, query.error, stableFilter]);
|
|
2463
|
+
const unavailable = stableFilter?.spaceIds !== void 0 && unavailableItemsSelection(query.error);
|
|
2419
2464
|
return {
|
|
2420
2465
|
allItems,
|
|
2421
2466
|
refetch: query.refetch,
|
|
2422
2467
|
fetchNextPage: query.fetchNextPage,
|
|
2423
2468
|
isFetchingNextPage: query.isFetchingNextPage,
|
|
2424
|
-
isExhausted: !query.hasNextPage,
|
|
2469
|
+
isExhausted: unavailable || !query.hasNextPage,
|
|
2425
2470
|
isLoading: query.isLoading,
|
|
2426
2471
|
isFetching: query.isFetching,
|
|
2427
2472
|
error: query.error,
|
|
2428
|
-
totalHint: query.data?.pages?.[0]?.total_hint
|
|
2473
|
+
totalHint: unavailable ? void 0 : query.data?.pages?.[0]?.total_hint
|
|
2429
2474
|
};
|
|
2430
2475
|
}
|
|
2431
2476
|
function useInfiniteChildren(path) {
|
|
@@ -2733,10 +2778,15 @@ function useMounts() {
|
|
|
2733
2778
|
useScopeKey();
|
|
2734
2779
|
const version = useSyncExternalStore(subscribeMounts, getMountVersion, getMountVersion);
|
|
2735
2780
|
const mounts = useMemo(() => getMounts(), [version]);
|
|
2781
|
+
const anchor = getAnchorRef();
|
|
2782
|
+
const selectedSpaces = useMemo(() => mounts.filter((ref) => ref.kind === "space" && (anchor?.kind === "account" || ref.id === anchor?.id)), [mounts, anchor]);
|
|
2783
|
+
const readSpaceIds = useMemo(() => selectedSpaces.map((ref) => ref.id).sort(), [selectedSpaces]);
|
|
2736
2784
|
return {
|
|
2737
2785
|
mounts,
|
|
2786
|
+
selectedSpaces,
|
|
2787
|
+
readSpaceIds,
|
|
2738
2788
|
homeAnchor: getHomeAnchor(),
|
|
2739
|
-
anchor
|
|
2789
|
+
anchor,
|
|
2740
2790
|
setAnchor: selectMount,
|
|
2741
2791
|
replaceMounts,
|
|
2742
2792
|
mount,
|