mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-17 22:03:50 +02:00
add @tanstack/query
This commit is contained in:
113
src/api/__tests__/entityQuerySync.test.js
Normal file
113
src/api/__tests__/entityQuerySync.test.js
Normal file
@@ -0,0 +1,113 @@
|
||||
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
|
||||
const mockRequest = vi.fn();
|
||||
const mockPatchAndRefetchActiveQuery = vi.fn(() => Promise.resolve());
|
||||
const mockFetchWithEntityPolicy = vi.fn();
|
||||
|
||||
const mockApplyCurrentUser = vi.fn((json) => ({ id: json.id || 'usr_me', ...json }));
|
||||
const mockApplyUser = vi.fn((json) => ({ ...json }));
|
||||
const mockApplyWorld = vi.fn((json) => ({ ...json }));
|
||||
|
||||
vi.mock('../../service/request', () => ({
|
||||
request: (...args) => mockRequest(...args)
|
||||
}));
|
||||
|
||||
vi.mock('../../stores', () => ({
|
||||
useUserStore: () => ({
|
||||
currentUser: { id: 'usr_me' },
|
||||
applyCurrentUser: mockApplyCurrentUser,
|
||||
applyUser: mockApplyUser
|
||||
}),
|
||||
useWorldStore: () => ({
|
||||
applyWorld: mockApplyWorld
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../query', () => ({
|
||||
entityQueryPolicies: {
|
||||
user: { staleTime: 20000, gcTime: 90000, retry: 1, refetchOnWindowFocus: false },
|
||||
avatar: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
|
||||
world: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
|
||||
worldCollection: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
|
||||
instance: { staleTime: 0, gcTime: 10000, retry: 0, refetchOnWindowFocus: false }
|
||||
},
|
||||
fetchWithEntityPolicy: (...args) => mockFetchWithEntityPolicy(...args),
|
||||
patchAndRefetchActiveQuery: (...args) =>
|
||||
mockPatchAndRefetchActiveQuery(...args),
|
||||
queryKeys: {
|
||||
user: (userId) => ['user', userId],
|
||||
avatar: (avatarId) => ['avatar', avatarId],
|
||||
world: (worldId) => ['world', worldId],
|
||||
worldsByUser: (params) => ['worlds', 'user', params.userId, params],
|
||||
instance: (worldId, instanceId) => ['instance', worldId, instanceId]
|
||||
}
|
||||
}));
|
||||
|
||||
import avatarRequest from '../avatar';
|
||||
import userRequest from '../user';
|
||||
import worldRequest from '../world';
|
||||
|
||||
describe('entity mutation query sync', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('saveCurrentUser patches and refetches active user query', async () => {
|
||||
mockRequest.mockResolvedValue({ id: 'usr_me', status: 'active' });
|
||||
|
||||
await userRequest.saveCurrentUser({ status: 'active' });
|
||||
|
||||
expect(mockPatchAndRefetchActiveQuery).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
queryKey: ['user', 'usr_me']
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test('saveAvatar patches and refetches active avatar query', async () => {
|
||||
mockRequest.mockResolvedValue({ id: 'avtr_1', name: 'Avatar' });
|
||||
|
||||
await avatarRequest.saveAvatar({ id: 'avtr_1', name: 'Avatar' });
|
||||
|
||||
expect(mockPatchAndRefetchActiveQuery).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
queryKey: ['avatar', 'avtr_1']
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test('saveWorld patches and refetches active world query', async () => {
|
||||
mockRequest.mockResolvedValue({ id: 'wrld_1', name: 'World' });
|
||||
|
||||
await worldRequest.saveWorld({ id: 'wrld_1', name: 'World' });
|
||||
|
||||
expect(mockPatchAndRefetchActiveQuery).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
queryKey: ['world', 'wrld_1']
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test('getCachedWorlds uses policy wrapper for world list data', async () => {
|
||||
mockFetchWithEntityPolicy.mockResolvedValue({
|
||||
data: {
|
||||
json: [{ id: 'wrld_1' }],
|
||||
params: { userId: 'usr_me', n: 50, offset: 0 }
|
||||
},
|
||||
cache: true
|
||||
});
|
||||
|
||||
const args = await worldRequest.getCachedWorlds({
|
||||
userId: 'usr_me',
|
||||
n: 50,
|
||||
offset: 0,
|
||||
sort: 'updated',
|
||||
order: 'descending',
|
||||
user: 'me',
|
||||
releaseStatus: 'all'
|
||||
});
|
||||
|
||||
expect(mockFetchWithEntityPolicy).toHaveBeenCalled();
|
||||
expect(args.cache).toBe(true);
|
||||
});
|
||||
});
|
||||
91
src/api/__tests__/favoriteQuerySync.test.js
Normal file
91
src/api/__tests__/favoriteQuerySync.test.js
Normal file
@@ -0,0 +1,91 @@
|
||||
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
|
||||
const mockRequest = vi.fn();
|
||||
const mockFetchWithEntityPolicy = vi.fn();
|
||||
const mockInvalidateQueries = vi.fn().mockResolvedValue();
|
||||
const mockHandleFavoriteAdd = vi.fn();
|
||||
const mockHandleFavoriteDelete = vi.fn();
|
||||
const mockHandleFavoriteGroupClear = vi.fn();
|
||||
|
||||
vi.mock('../../service/request', () => ({
|
||||
request: (...args) => mockRequest(...args)
|
||||
}));
|
||||
|
||||
vi.mock('../../stores', () => ({
|
||||
useFavoriteStore: () => ({
|
||||
handleFavoriteAdd: (...args) => mockHandleFavoriteAdd(...args),
|
||||
handleFavoriteDelete: (...args) => mockHandleFavoriteDelete(...args),
|
||||
handleFavoriteGroupClear: (...args) =>
|
||||
mockHandleFavoriteGroupClear(...args)
|
||||
}),
|
||||
useUserStore: () => ({
|
||||
currentUser: { id: 'usr_me' }
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../query', () => ({
|
||||
entityQueryPolicies: {
|
||||
favoriteCollection: {
|
||||
staleTime: 60000,
|
||||
gcTime: 300000,
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false
|
||||
}
|
||||
},
|
||||
fetchWithEntityPolicy: (...args) => mockFetchWithEntityPolicy(...args),
|
||||
queryClient: {
|
||||
invalidateQueries: (...args) => mockInvalidateQueries(...args)
|
||||
},
|
||||
queryKeys: {
|
||||
favoriteLimits: () => ['favorite', 'limits'],
|
||||
favorites: (params) => ['favorite', 'items', params],
|
||||
favoriteGroups: (params) => ['favorite', 'groups', params],
|
||||
favoriteWorlds: (params) => ['favorite', 'worlds', params],
|
||||
favoriteAvatars: (params) => ['favorite', 'avatars', params]
|
||||
}
|
||||
}));
|
||||
|
||||
import favoriteRequest from '../favorite';
|
||||
|
||||
describe('favorite query sync', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('cached favorite reads go through fetchWithEntityPolicy', async () => {
|
||||
mockFetchWithEntityPolicy.mockResolvedValue({
|
||||
data: { json: [], params: { n: 300, offset: 0 } },
|
||||
cache: true
|
||||
});
|
||||
|
||||
const args = await favoriteRequest.getCachedFavorites({
|
||||
n: 300,
|
||||
offset: 0
|
||||
});
|
||||
|
||||
expect(mockFetchWithEntityPolicy).toHaveBeenCalled();
|
||||
expect(args.cache).toBe(true);
|
||||
});
|
||||
|
||||
test('favorite mutations invalidate active favorite queries', async () => {
|
||||
mockRequest.mockResolvedValue({ ok: true });
|
||||
|
||||
await favoriteRequest.addFavorite({ type: 'world', favoriteId: 'wrld_1' });
|
||||
await favoriteRequest.deleteFavorite({ objectId: 'fav_1' });
|
||||
await favoriteRequest.saveFavoriteGroup({
|
||||
type: 'world',
|
||||
group: 'worlds1',
|
||||
displayName: 'Worlds'
|
||||
});
|
||||
await favoriteRequest.clearFavoriteGroup({
|
||||
type: 'world',
|
||||
group: 'worlds1'
|
||||
});
|
||||
|
||||
expect(mockInvalidateQueries).toHaveBeenCalledTimes(4);
|
||||
expect(mockInvalidateQueries).toHaveBeenCalledWith({
|
||||
queryKey: ['favorite'],
|
||||
refetchType: 'active'
|
||||
});
|
||||
});
|
||||
});
|
||||
72
src/api/__tests__/friendQuerySync.test.js
Normal file
72
src/api/__tests__/friendQuerySync.test.js
Normal file
@@ -0,0 +1,72 @@
|
||||
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
|
||||
const mockRequest = vi.fn();
|
||||
const mockFetchWithEntityPolicy = vi.fn();
|
||||
const mockInvalidateQueries = vi.fn().mockResolvedValue();
|
||||
const mockApplyUser = vi.fn((json) => json);
|
||||
|
||||
vi.mock('../../service/request', () => ({
|
||||
request: (...args) => mockRequest(...args)
|
||||
}));
|
||||
|
||||
vi.mock('../../stores/user', () => ({
|
||||
useUserStore: () => ({
|
||||
applyUser: (...args) => mockApplyUser(...args)
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../query', () => ({
|
||||
entityQueryPolicies: {
|
||||
friendList: {
|
||||
staleTime: 20000,
|
||||
gcTime: 90000,
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false
|
||||
}
|
||||
},
|
||||
fetchWithEntityPolicy: (...args) => mockFetchWithEntityPolicy(...args),
|
||||
queryClient: {
|
||||
invalidateQueries: (...args) => mockInvalidateQueries(...args)
|
||||
},
|
||||
queryKeys: {
|
||||
friends: (params) => ['friends', params]
|
||||
}
|
||||
}));
|
||||
|
||||
import friendRequest from '../friend';
|
||||
|
||||
describe('friend query sync', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('getCachedFriends uses query policy wrapper', async () => {
|
||||
mockFetchWithEntityPolicy.mockResolvedValue({
|
||||
data: {
|
||||
json: [{ id: 'usr_1', displayName: 'A' }],
|
||||
params: { n: 50, offset: 0 }
|
||||
},
|
||||
cache: true
|
||||
});
|
||||
|
||||
const args = await friendRequest.getCachedFriends({ n: 50, offset: 0 });
|
||||
|
||||
expect(mockFetchWithEntityPolicy).toHaveBeenCalled();
|
||||
expect(args.cache).toBe(true);
|
||||
expect(args.json[0].id).toBe('usr_1');
|
||||
});
|
||||
|
||||
test('friend mutations invalidate active friends queries', async () => {
|
||||
mockRequest.mockResolvedValue({ ok: true });
|
||||
|
||||
await friendRequest.sendFriendRequest({ userId: 'usr_1' });
|
||||
await friendRequest.cancelFriendRequest({ userId: 'usr_1' });
|
||||
await friendRequest.deleteFriend({ userId: 'usr_1' });
|
||||
|
||||
expect(mockInvalidateQueries).toHaveBeenCalledTimes(3);
|
||||
expect(mockInvalidateQueries).toHaveBeenCalledWith({
|
||||
queryKey: ['friends'],
|
||||
refetchType: 'active'
|
||||
});
|
||||
});
|
||||
});
|
||||
101
src/api/__tests__/groupQuerySync.test.js
Normal file
101
src/api/__tests__/groupQuerySync.test.js
Normal file
@@ -0,0 +1,101 @@
|
||||
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
|
||||
const mockRequest = vi.fn();
|
||||
const mockFetchWithEntityPolicy = vi.fn();
|
||||
const mockInvalidateQueries = vi.fn().mockResolvedValue();
|
||||
const mockApplyGroup = vi.fn((json) => json);
|
||||
|
||||
vi.mock('../../service/request', () => ({
|
||||
request: (...args) => mockRequest(...args)
|
||||
}));
|
||||
|
||||
vi.mock('../../stores', () => ({
|
||||
useGroupStore: () => ({
|
||||
applyGroup: (...args) => mockApplyGroup(...args)
|
||||
}),
|
||||
useUserStore: () => ({
|
||||
currentUser: { id: 'usr_me' }
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../query', () => ({
|
||||
entityQueryPolicies: {
|
||||
group: {
|
||||
staleTime: 60000,
|
||||
gcTime: 300000,
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false
|
||||
},
|
||||
groupCollection: {
|
||||
staleTime: 60000,
|
||||
gcTime: 300000,
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false
|
||||
}
|
||||
},
|
||||
fetchWithEntityPolicy: (...args) => mockFetchWithEntityPolicy(...args),
|
||||
queryClient: {
|
||||
invalidateQueries: (...args) => mockInvalidateQueries(...args)
|
||||
},
|
||||
queryKeys: {
|
||||
group: (groupId, includeRoles) => ['group', groupId, Boolean(includeRoles)],
|
||||
groupPosts: (params) => ['group', params.groupId, 'posts', params],
|
||||
groupMember: (params) => ['group', params.groupId, 'member', params.userId],
|
||||
groupMembers: (params) => ['group', params.groupId, 'members', params],
|
||||
groupGallery: (params) => ['group', params.groupId, 'gallery', params.galleryId, params],
|
||||
groupCalendar: (groupId) => ['group', groupId, 'calendar'],
|
||||
groupCalendarEvent: (params) => ['group', params.groupId, 'calendarEvent', params.eventId]
|
||||
}
|
||||
}));
|
||||
|
||||
import groupRequest from '../group';
|
||||
|
||||
describe('group query sync', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('cached group resources use fetchWithEntityPolicy', async () => {
|
||||
mockFetchWithEntityPolicy.mockResolvedValue({
|
||||
data: { json: [], params: { groupId: 'grp_1', n: 100, offset: 0 } },
|
||||
cache: true
|
||||
});
|
||||
|
||||
const a = await groupRequest.getCachedGroupMembers({
|
||||
groupId: 'grp_1',
|
||||
n: 100,
|
||||
offset: 0,
|
||||
sort: 'joinedAt:desc'
|
||||
});
|
||||
const b = await groupRequest.getCachedGroupGallery({
|
||||
groupId: 'grp_1',
|
||||
galleryId: 'gal_1',
|
||||
n: 100,
|
||||
offset: 0
|
||||
});
|
||||
|
||||
expect(mockFetchWithEntityPolicy).toHaveBeenCalledTimes(2);
|
||||
expect(a.cache && b.cache).toBe(true);
|
||||
});
|
||||
|
||||
test('group mutations invalidate scoped active group queries', async () => {
|
||||
mockRequest.mockResolvedValue({ ok: true });
|
||||
|
||||
await groupRequest.setGroupRepresentation('grp_1', {
|
||||
isRepresenting: true
|
||||
});
|
||||
await groupRequest.deleteGroupPost({
|
||||
groupId: 'grp_1',
|
||||
postId: 'post_1'
|
||||
});
|
||||
await groupRequest.setGroupMemberProps('usr_me', 'grp_1', {
|
||||
visibility: 'visible'
|
||||
});
|
||||
|
||||
expect(mockInvalidateQueries).toHaveBeenCalledTimes(3);
|
||||
expect(mockInvalidateQueries).toHaveBeenCalledWith({
|
||||
queryKey: ['group', 'grp_1'],
|
||||
refetchType: 'active'
|
||||
});
|
||||
});
|
||||
});
|
||||
100
src/api/__tests__/mediaQuerySync.test.js
Normal file
100
src/api/__tests__/mediaQuerySync.test.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
|
||||
const mockRequest = vi.fn();
|
||||
const mockFetchWithEntityPolicy = vi.fn();
|
||||
const mockInvalidateQueries = vi.fn().mockResolvedValue();
|
||||
const mockRemoveQueries = vi.fn();
|
||||
|
||||
vi.mock('../../service/request', () => ({
|
||||
request: (...args) => mockRequest(...args)
|
||||
}));
|
||||
|
||||
vi.mock('../../stores', () => ({
|
||||
useUserStore: () => ({
|
||||
currentUser: { id: 'usr_me' }
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../query', () => ({
|
||||
entityQueryPolicies: {
|
||||
galleryCollection: {
|
||||
staleTime: 60000,
|
||||
gcTime: 300000,
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false
|
||||
},
|
||||
inventoryCollection: {
|
||||
staleTime: 20000,
|
||||
gcTime: 120000,
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false
|
||||
},
|
||||
fileObject: {
|
||||
staleTime: 60000,
|
||||
gcTime: 300000,
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false
|
||||
}
|
||||
},
|
||||
fetchWithEntityPolicy: (...args) => mockFetchWithEntityPolicy(...args),
|
||||
queryClient: {
|
||||
invalidateQueries: (...args) => mockInvalidateQueries(...args),
|
||||
removeQueries: (...args) => mockRemoveQueries(...args)
|
||||
},
|
||||
queryKeys: {
|
||||
galleryFiles: (params) => ['gallery', 'files', params],
|
||||
prints: (params) => ['gallery', 'prints', params],
|
||||
print: (printId) => ['gallery', 'print', printId],
|
||||
inventoryItems: (params) => ['inventory', 'items', params],
|
||||
userInventoryItem: (params) => ['inventory', 'item', params.userId, params.inventoryId],
|
||||
file: (fileId) => ['file', fileId]
|
||||
}
|
||||
}));
|
||||
|
||||
import inventoryRequest from '../inventory';
|
||||
import miscRequest from '../misc';
|
||||
import vrcPlusIconRequest from '../vrcPlusIcon';
|
||||
import vrcPlusImageRequest from '../vrcPlusImage';
|
||||
|
||||
describe('media and inventory query sync', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('cached media/inventory reads go through fetchWithEntityPolicy', async () => {
|
||||
mockFetchWithEntityPolicy.mockResolvedValue({
|
||||
data: { json: [], params: {} },
|
||||
cache: true
|
||||
});
|
||||
|
||||
const a = await vrcPlusIconRequest.getCachedFileList({ tag: 'icon', n: 100 });
|
||||
const b = await vrcPlusImageRequest.getCachedPrints({ n: 100 });
|
||||
const c = await inventoryRequest.getCachedInventoryItems({
|
||||
n: 100,
|
||||
offset: 0,
|
||||
order: 'newest'
|
||||
});
|
||||
const d = await miscRequest.getCachedFile({ fileId: 'file_1' });
|
||||
|
||||
expect(mockFetchWithEntityPolicy).toHaveBeenCalledTimes(4);
|
||||
expect(a.cache && b.cache && c.cache && d.cache).toBe(true);
|
||||
});
|
||||
|
||||
test('media mutations invalidate gallery queries and file delete removes file query', async () => {
|
||||
mockRequest.mockResolvedValue({ ok: true });
|
||||
|
||||
await vrcPlusIconRequest.deleteFile('file_icon_1');
|
||||
await vrcPlusImageRequest.deletePrint('print_1');
|
||||
await vrcPlusImageRequest.uploadEmoji('img', { tag: 'emoji' });
|
||||
await miscRequest.deleteFile('file_misc_1');
|
||||
|
||||
expect(mockInvalidateQueries).toHaveBeenCalledWith({
|
||||
queryKey: ['gallery'],
|
||||
refetchType: 'active'
|
||||
});
|
||||
expect(mockRemoveQueries).toHaveBeenCalledWith({
|
||||
queryKey: ['file', 'file_misc_1'],
|
||||
exact: true
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,11 @@
|
||||
import { request } from '../service/request';
|
||||
import { useUserStore } from '../stores';
|
||||
import {
|
||||
entityQueryPolicies,
|
||||
fetchWithEntityPolicy,
|
||||
patchAndRefetchActiveQuery,
|
||||
queryKeys
|
||||
} from '../query';
|
||||
|
||||
const avatarReq = {
|
||||
/**
|
||||
@@ -17,6 +23,22 @@ const avatarReq = {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch avatar from query cache if fresh. Otherwise, calls API.
|
||||
* @param {{avatarId: string}} params
|
||||
* @returns {Promise<{json: any, ref?: any, cache?: boolean, params: {avatarId: string}}>}
|
||||
*/
|
||||
getCachedAvatar(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.avatar(params.avatarId),
|
||||
policy: entityQueryPolicies.avatar,
|
||||
queryFn: () => avatarReq.getAvatar(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* @type {import('../types/api/avatar').GetAvatars}
|
||||
*/
|
||||
@@ -46,6 +68,12 @@ const avatarReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
patchAndRefetchActiveQuery({
|
||||
queryKey: queryKeys.avatar(params.id),
|
||||
nextData: args
|
||||
}).catch((err) => {
|
||||
console.error('Failed to refresh avatar query after mutation:', err);
|
||||
});
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -64,7 +92,20 @@ const avatarReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
userStore.applyCurrentUser(json);
|
||||
const ref = userStore.applyCurrentUser(json);
|
||||
patchAndRefetchActiveQuery({
|
||||
queryKey: queryKeys.user(ref.id),
|
||||
nextData: {
|
||||
json,
|
||||
params: { userId: ref.id },
|
||||
ref
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.error(
|
||||
'Failed to refresh current user query after avatar select:',
|
||||
err
|
||||
);
|
||||
});
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -83,7 +124,20 @@ const avatarReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
userStore.applyCurrentUser(json);
|
||||
const ref = userStore.applyCurrentUser(json);
|
||||
patchAndRefetchActiveQuery({
|
||||
queryKey: queryKeys.user(ref.id),
|
||||
nextData: {
|
||||
json,
|
||||
params: { userId: ref.id },
|
||||
ref
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.error(
|
||||
'Failed to refresh current user query after fallback avatar select:',
|
||||
err
|
||||
);
|
||||
});
|
||||
return args;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,10 +1,27 @@
|
||||
import { useFavoriteStore, useUserStore } from '../stores';
|
||||
import { request } from '../service/request';
|
||||
import {
|
||||
entityQueryPolicies,
|
||||
fetchWithEntityPolicy,
|
||||
queryClient,
|
||||
queryKeys
|
||||
} from '../query';
|
||||
|
||||
function getCurrentUserId() {
|
||||
return useUserStore().currentUser.id;
|
||||
}
|
||||
|
||||
function refetchActiveFavoriteQueries() {
|
||||
queryClient
|
||||
.invalidateQueries({
|
||||
queryKey: ['favorite'],
|
||||
refetchType: 'active'
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Failed to refresh favorite queries:', err);
|
||||
});
|
||||
}
|
||||
|
||||
const favoriteReq = {
|
||||
getFavoriteLimits() {
|
||||
return request('auth/user/favoritelimits', {
|
||||
@@ -17,6 +34,17 @@ const favoriteReq = {
|
||||
});
|
||||
},
|
||||
|
||||
getCachedFavoriteLimits() {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.favoriteLimits(),
|
||||
policy: entityQueryPolicies.favoriteCollection,
|
||||
queryFn: () => favoriteReq.getFavoriteLimits()
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* @type {import('../types/api/favorite').GetFavorites}
|
||||
*/
|
||||
@@ -33,6 +61,17 @@ const favoriteReq = {
|
||||
});
|
||||
},
|
||||
|
||||
getCachedFavorites(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.favorites(params),
|
||||
policy: entityQueryPolicies.favoriteCollection,
|
||||
queryFn: () => favoriteReq.getFavorites(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* @type {import('../types/api/favorite').AddFavorite}
|
||||
*/
|
||||
@@ -46,6 +85,7 @@ const favoriteReq = {
|
||||
params
|
||||
};
|
||||
useFavoriteStore().handleFavoriteAdd(args);
|
||||
refetchActiveFavoriteQueries();
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -63,6 +103,7 @@ const favoriteReq = {
|
||||
params
|
||||
};
|
||||
useFavoriteStore().handleFavoriteDelete(params.objectId);
|
||||
refetchActiveFavoriteQueries();
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -84,6 +125,17 @@ const favoriteReq = {
|
||||
});
|
||||
},
|
||||
|
||||
getCachedFavoriteGroups(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.favoriteGroups(params),
|
||||
policy: entityQueryPolicies.favoriteCollection,
|
||||
queryFn: () => favoriteReq.getFavoriteGroups(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {{ type: string, group: string, displayName?: string, visibility?: string }} params group is a name
|
||||
@@ -101,6 +153,7 @@ const favoriteReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveFavoriteQueries();
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -125,6 +178,7 @@ const favoriteReq = {
|
||||
params
|
||||
};
|
||||
useFavoriteStore().handleFavoriteGroupClear(args);
|
||||
refetchActiveFavoriteQueries();
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -145,6 +199,17 @@ const favoriteReq = {
|
||||
});
|
||||
},
|
||||
|
||||
getCachedFavoriteWorlds(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.favoriteWorlds(params),
|
||||
policy: entityQueryPolicies.favoriteCollection,
|
||||
queryFn: () => favoriteReq.getFavoriteWorlds(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* @type {import('../types/api/favorite').GetFavoriteAvatars}
|
||||
*/
|
||||
@@ -159,6 +224,17 @@ const favoriteReq = {
|
||||
};
|
||||
return args;
|
||||
});
|
||||
},
|
||||
|
||||
getCachedFavoriteAvatars(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.favoriteAvatars(params),
|
||||
policy: entityQueryPolicies.favoriteCollection,
|
||||
queryFn: () => favoriteReq.getFavoriteAvatars(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
import { request } from '../service/request';
|
||||
import { useUserStore } from '../stores/user';
|
||||
import {
|
||||
entityQueryPolicies,
|
||||
fetchWithEntityPolicy,
|
||||
queryClient,
|
||||
queryKeys
|
||||
} from '../query';
|
||||
|
||||
function refetchActiveFriendListQueries() {
|
||||
queryClient
|
||||
.invalidateQueries({
|
||||
queryKey: ['friends'],
|
||||
refetchType: 'active'
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Failed to refresh friend list queries:', err);
|
||||
});
|
||||
}
|
||||
|
||||
const friendReq = {
|
||||
/**
|
||||
@@ -27,6 +44,22 @@ const friendReq = {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch friends from query cache if still fresh. Otherwise, calls API.
|
||||
* @param {{ n: number, offset: number, offline?: boolean }} params
|
||||
* @returns {Promise<{json: any, params: { n: number, offset: number, offline?: boolean }, cache?: boolean}>}
|
||||
*/
|
||||
getCachedFriends(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.friends(params),
|
||||
policy: entityQueryPolicies.friendList,
|
||||
queryFn: () => friendReq.getFriends(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {{ userId: string }} params
|
||||
* @returns {Promise<{json: any, params: { userId: string }}>}
|
||||
@@ -39,6 +72,7 @@ const friendReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveFriendListQueries();
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -55,6 +89,7 @@ const friendReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveFriendListQueries();
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -72,6 +107,7 @@ const friendReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveFriendListQueries();
|
||||
return args;
|
||||
});
|
||||
},
|
||||
|
||||
130
src/api/group.js
130
src/api/group.js
@@ -1,9 +1,29 @@
|
||||
import { useGroupStore, useUserStore } from '../stores';
|
||||
import { request } from '../service/request';
|
||||
import {
|
||||
entityQueryPolicies,
|
||||
fetchWithEntityPolicy,
|
||||
queryClient,
|
||||
queryKeys
|
||||
} from '../query';
|
||||
|
||||
function getCurrentUserId() {
|
||||
return useUserStore().currentUser.id;
|
||||
}
|
||||
|
||||
function refetchActiveGroupScope(groupId) {
|
||||
if (!groupId) {
|
||||
return;
|
||||
}
|
||||
queryClient
|
||||
.invalidateQueries({
|
||||
queryKey: ['group', groupId],
|
||||
refetchType: 'active'
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Failed to refresh scoped group queries:', err);
|
||||
});
|
||||
}
|
||||
const groupReq = {
|
||||
/**
|
||||
* @param {string} groupId
|
||||
@@ -20,6 +40,7 @@ const groupReq = {
|
||||
groupId,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -52,6 +73,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -78,26 +100,18 @@ const groupReq = {
|
||||
* @return { Promise<{json: any, ref: any, cache?: boolean, params}> }
|
||||
*/
|
||||
getCachedGroup(params) {
|
||||
const groupStore = useGroupStore();
|
||||
return new Promise((resolve, reject) => {
|
||||
const ref = groupStore.cachedGroups.get(params.groupId);
|
||||
if (typeof ref === 'undefined') {
|
||||
groupReq
|
||||
.getGroup(params)
|
||||
.then((args) => {
|
||||
args.ref = groupStore.applyGroup(args.json);
|
||||
resolve(args);
|
||||
})
|
||||
.catch(reject);
|
||||
} else {
|
||||
resolve({
|
||||
cache: true,
|
||||
json: ref,
|
||||
params,
|
||||
ref
|
||||
});
|
||||
}
|
||||
});
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.group(params.groupId, params.includeRoles),
|
||||
policy: entityQueryPolicies.group,
|
||||
queryFn: () => groupReq.getGroup(params).then((args) => {
|
||||
const groupStore = useGroupStore();
|
||||
args.ref = groupStore.applyGroup(args.json);
|
||||
return args;
|
||||
})
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
/**
|
||||
* @param {{ userId: string }} params
|
||||
@@ -141,6 +155,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -156,6 +171,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -195,6 +211,7 @@ const groupReq = {
|
||||
groupId,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -217,6 +234,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -239,6 +257,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -273,6 +292,16 @@ const groupReq = {
|
||||
return args;
|
||||
});
|
||||
},
|
||||
getCachedGroupPosts(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.groupPosts(params),
|
||||
policy: entityQueryPolicies.groupCollection,
|
||||
queryFn: () => groupReq.getGroupPosts(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
editGroupPost(params) {
|
||||
return request(`groups/${params.groupId}/posts/${params.postId}`, {
|
||||
method: 'PUT',
|
||||
@@ -282,6 +311,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -294,6 +324,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -315,6 +346,16 @@ const groupReq = {
|
||||
return args;
|
||||
});
|
||||
},
|
||||
getCachedGroupMember(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.groupMember(params),
|
||||
policy: entityQueryPolicies.groupCollection,
|
||||
queryFn: () => groupReq.getGroupMember(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
/**
|
||||
* @param {{
|
||||
* groupId: string,
|
||||
@@ -335,6 +376,16 @@ const groupReq = {
|
||||
return args;
|
||||
});
|
||||
},
|
||||
getCachedGroupMembers(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.groupMembers(params),
|
||||
policy: entityQueryPolicies.groupCollection,
|
||||
queryFn: () => groupReq.getGroupMembers(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
/**
|
||||
* @param {{
|
||||
* groupId: string,
|
||||
@@ -370,6 +421,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -388,6 +440,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -427,6 +480,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -445,6 +499,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -456,6 +511,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -496,6 +552,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -510,7 +567,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -526,6 +583,7 @@ const groupReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGroupScope(params.groupId);
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -698,6 +756,16 @@ const groupReq = {
|
||||
return args;
|
||||
});
|
||||
},
|
||||
getCachedGroupGallery(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.groupGallery(params),
|
||||
policy: entityQueryPolicies.groupCollection,
|
||||
queryFn: () => groupReq.getGroupGallery(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
getGroupCalendar(groupId) {
|
||||
return request(`calendar/${groupId}`, {
|
||||
@@ -712,6 +780,16 @@ const groupReq = {
|
||||
return args;
|
||||
});
|
||||
},
|
||||
getCachedGroupCalendar(groupId) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.groupCalendar(groupId),
|
||||
policy: entityQueryPolicies.groupCollection,
|
||||
queryFn: () => groupReq.getGroupCalendar(groupId)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {{
|
||||
@@ -731,6 +809,16 @@ const groupReq = {
|
||||
return args;
|
||||
});
|
||||
},
|
||||
getCachedGroupCalendarEvent(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.groupCalendarEvent(params),
|
||||
policy: entityQueryPolicies.groupCollection,
|
||||
queryFn: () => groupReq.getGroupCalendarEvent(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* @type {import('../types/api/group').GetCalendars}
|
||||
|
||||
@@ -3,6 +3,12 @@ import { toast } from 'vue-sonner';
|
||||
import { i18n } from '../plugin/i18n';
|
||||
import { request } from '../service/request';
|
||||
import { useInstanceStore } from '../stores';
|
||||
import {
|
||||
entityQueryPolicies,
|
||||
fetchWithEntityPolicy,
|
||||
patchAndRefetchActiveQuery,
|
||||
queryKeys
|
||||
} from '../query';
|
||||
|
||||
const instanceReq = {
|
||||
/**
|
||||
@@ -27,28 +33,14 @@ const instanceReq = {
|
||||
* @returns {Promise<{json: any, ref: any, cache?: boolean, params}>}
|
||||
*/
|
||||
getCachedInstance(params) {
|
||||
const instanceStore = useInstanceStore();
|
||||
return new Promise((resolve, reject) => {
|
||||
const ref = instanceStore.cachedInstances.get(
|
||||
`${params.worldId}:${params.instanceId}`
|
||||
);
|
||||
if (typeof ref === 'undefined') {
|
||||
instanceReq
|
||||
.getInstance(params)
|
||||
.then((args) => {
|
||||
args.ref = instanceStore.applyInstance(args.json);
|
||||
resolve(args);
|
||||
})
|
||||
.catch(reject);
|
||||
} else {
|
||||
resolve({
|
||||
cache: true,
|
||||
json: ref,
|
||||
params,
|
||||
ref
|
||||
});
|
||||
}
|
||||
});
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.instance(params.worldId, params.instanceId),
|
||||
policy: entityQueryPolicies.instance,
|
||||
queryFn: () => instanceReq.getInstance(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -65,6 +57,15 @@ const instanceReq = {
|
||||
params
|
||||
};
|
||||
args.ref = instanceStore.applyInstance(json);
|
||||
patchAndRefetchActiveQuery({
|
||||
queryKey: queryKeys.instance(args.ref.worldId, args.ref.instanceId),
|
||||
nextData: args
|
||||
}).catch((err) => {
|
||||
console.error(
|
||||
'Failed to refresh instance query after instance creation:',
|
||||
err
|
||||
);
|
||||
});
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -107,6 +108,15 @@ const instanceReq = {
|
||||
params
|
||||
};
|
||||
args.ref = instanceStore.applyInstance(json);
|
||||
patchAndRefetchActiveQuery({
|
||||
queryKey: queryKeys.instance(args.ref.worldId, args.ref.instanceId),
|
||||
nextData: args
|
||||
}).catch((err) => {
|
||||
console.error(
|
||||
'Failed to refresh instance query after short-name resolve:',
|
||||
err
|
||||
);
|
||||
});
|
||||
return args;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,4 +1,21 @@
|
||||
import { request } from '../service/request';
|
||||
import {
|
||||
entityQueryPolicies,
|
||||
fetchWithEntityPolicy,
|
||||
queryClient,
|
||||
queryKeys
|
||||
} from '../query';
|
||||
|
||||
function refetchActiveInventoryQueries() {
|
||||
queryClient
|
||||
.invalidateQueries({
|
||||
queryKey: ['inventory'],
|
||||
refetchType: 'active'
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Failed to refresh inventory queries:', err);
|
||||
});
|
||||
}
|
||||
|
||||
const inventoryReq = {
|
||||
/**
|
||||
@@ -20,6 +37,17 @@ const inventoryReq = {
|
||||
});
|
||||
},
|
||||
|
||||
getCachedUserInventoryItem(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.userInventoryItem(params),
|
||||
policy: entityQueryPolicies.inventoryCollection,
|
||||
queryFn: () => inventoryReq.getUserInventoryItem(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {{ inventoryId: string }} params
|
||||
* @returns {Promise<{json: any, params}>}
|
||||
@@ -54,6 +82,17 @@ const inventoryReq = {
|
||||
});
|
||||
},
|
||||
|
||||
getCachedInventoryItems(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.inventoryItems(params),
|
||||
policy: entityQueryPolicies.inventoryCollection,
|
||||
queryFn: () => inventoryReq.getInventoryItems(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {{ inventoryId: string }} params
|
||||
* @returns {Promise<{json: any, params}>}
|
||||
@@ -67,6 +106,7 @@ const inventoryReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveInventoryQueries();
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -102,6 +142,7 @@ const inventoryReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveInventoryQueries();
|
||||
return args;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import { request } from '../service/request';
|
||||
import { useUserStore } from '../stores';
|
||||
import {
|
||||
entityQueryPolicies,
|
||||
fetchWithEntityPolicy,
|
||||
queryClient,
|
||||
queryKeys
|
||||
} from '../query';
|
||||
|
||||
function getCurrentUserId() {
|
||||
return useUserStore().currentUser.id;
|
||||
@@ -18,6 +24,17 @@ const miscReq = {
|
||||
});
|
||||
},
|
||||
|
||||
getCachedFile(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.file(params.fileId),
|
||||
policy: entityQueryPolicies.fileObject,
|
||||
queryFn: () => miscReq.getFile(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
saveNote(params) {
|
||||
return request('userNotes', {
|
||||
method: 'POST',
|
||||
@@ -192,6 +209,10 @@ const miscReq = {
|
||||
json,
|
||||
fileId
|
||||
};
|
||||
queryClient.removeQueries({
|
||||
queryKey: queryKeys.file(fileId),
|
||||
exact: true
|
||||
});
|
||||
return args;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import { request } from '../service/request';
|
||||
import { useUserStore } from '../stores';
|
||||
import {
|
||||
entityQueryPolicies,
|
||||
fetchWithEntityPolicy,
|
||||
patchAndRefetchActiveQuery,
|
||||
queryKeys
|
||||
} from '../query';
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
@@ -39,26 +45,14 @@ const userReq = {
|
||||
* @type {import('../types/api/user').GetCachedUser}
|
||||
*/
|
||||
getCachedUser(params) {
|
||||
const userStore = useUserStore();
|
||||
return new Promise((resolve, reject) => {
|
||||
const ref = userStore.cachedUsers.get(params.userId);
|
||||
if (typeof ref === 'undefined') {
|
||||
userReq
|
||||
.getUser(params)
|
||||
.then((args) => {
|
||||
args.ref = userStore.applyUser(args.json);
|
||||
resolve(args);
|
||||
})
|
||||
.catch(reject);
|
||||
} else {
|
||||
resolve({
|
||||
cache: true,
|
||||
json: ref,
|
||||
params,
|
||||
ref
|
||||
});
|
||||
}
|
||||
});
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.user(params.userId),
|
||||
policy: entityQueryPolicies.user,
|
||||
queryFn: () => userReq.getUser(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -149,6 +143,12 @@ const userReq = {
|
||||
params,
|
||||
ref: userStore.applyCurrentUser(json)
|
||||
};
|
||||
patchAndRefetchActiveQuery({
|
||||
queryKey: queryKeys.user(args.ref.id),
|
||||
nextData: args
|
||||
}).catch((err) => {
|
||||
console.error('Failed to refresh user query after mutation:', err);
|
||||
});
|
||||
return args;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,4 +1,21 @@
|
||||
import { request } from '../service/request';
|
||||
import {
|
||||
entityQueryPolicies,
|
||||
fetchWithEntityPolicy,
|
||||
queryClient,
|
||||
queryKeys
|
||||
} from '../query';
|
||||
|
||||
function refetchActiveGalleryQueries() {
|
||||
queryClient
|
||||
.invalidateQueries({
|
||||
queryKey: ['gallery'],
|
||||
refetchType: 'active'
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Failed to refresh gallery queries:', err);
|
||||
});
|
||||
}
|
||||
|
||||
const VRCPlusIconsReq = {
|
||||
getFileList(params) {
|
||||
@@ -14,6 +31,17 @@ const VRCPlusIconsReq = {
|
||||
});
|
||||
},
|
||||
|
||||
getCachedFileList(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.galleryFiles(params),
|
||||
policy: entityQueryPolicies.galleryCollection,
|
||||
queryFn: () => VRCPlusIconsReq.getFileList(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
deleteFile(fileId) {
|
||||
return request(`file/${fileId}`, {
|
||||
method: 'DELETE'
|
||||
@@ -22,6 +50,7 @@ const VRCPlusIconsReq = {
|
||||
json,
|
||||
fileId
|
||||
};
|
||||
refetchActiveGalleryQueries();
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -40,6 +69,7 @@ const VRCPlusIconsReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGalleryQueries();
|
||||
return args;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,9 +1,26 @@
|
||||
import { request } from '../service/request';
|
||||
import { useUserStore } from '../stores';
|
||||
import {
|
||||
entityQueryPolicies,
|
||||
fetchWithEntityPolicy,
|
||||
queryClient,
|
||||
queryKeys
|
||||
} from '../query';
|
||||
|
||||
function getCurrentUserId() {
|
||||
return useUserStore().currentUser.id;
|
||||
}
|
||||
|
||||
function refetchActiveGalleryQueries() {
|
||||
queryClient
|
||||
.invalidateQueries({
|
||||
queryKey: ['gallery'],
|
||||
refetchType: 'active'
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Failed to refresh gallery queries:', err);
|
||||
});
|
||||
}
|
||||
const vrcPlusImageReq = {
|
||||
uploadGalleryImage(imageData) {
|
||||
const params = {
|
||||
@@ -19,6 +36,7 @@ const vrcPlusImageReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGalleryQueries();
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -34,6 +52,7 @@ const vrcPlusImageReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGalleryQueries();
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -51,6 +70,17 @@ const vrcPlusImageReq = {
|
||||
});
|
||||
},
|
||||
|
||||
getCachedPrints(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.prints(params),
|
||||
policy: entityQueryPolicies.galleryCollection,
|
||||
queryFn: () => vrcPlusImageReq.getPrints(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
deletePrint(printId) {
|
||||
return request(`prints/${printId}`, {
|
||||
method: 'DELETE'
|
||||
@@ -59,6 +89,7 @@ const vrcPlusImageReq = {
|
||||
json,
|
||||
printId
|
||||
};
|
||||
refetchActiveGalleryQueries();
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -74,6 +105,7 @@ const vrcPlusImageReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGalleryQueries();
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -90,6 +122,17 @@ const vrcPlusImageReq = {
|
||||
});
|
||||
},
|
||||
|
||||
getCachedPrint(params) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.print(params.printId),
|
||||
policy: entityQueryPolicies.galleryCollection,
|
||||
queryFn: () => vrcPlusImageReq.getPrint(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
uploadEmoji(imageData, params) {
|
||||
return request('file/image', {
|
||||
uploadImage: true,
|
||||
@@ -101,6 +144,7 @@ const vrcPlusImageReq = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
refetchActiveGalleryQueries();
|
||||
return args;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import { request } from '../service/request';
|
||||
import { useWorldStore } from '../stores';
|
||||
import {
|
||||
entityQueryPolicies,
|
||||
fetchWithEntityPolicy,
|
||||
patchAndRefetchActiveQuery,
|
||||
queryKeys
|
||||
} from '../query';
|
||||
|
||||
const worldReq = {
|
||||
/**
|
||||
@@ -24,26 +30,14 @@ const worldReq = {
|
||||
* @returns {Promise<{json: any, ref: any, cache?: boolean, params}>}
|
||||
*/
|
||||
getCachedWorld(params) {
|
||||
const worldStore = useWorldStore();
|
||||
return new Promise((resolve, reject) => {
|
||||
const ref = worldStore.cachedWorlds.get(params.worldId);
|
||||
if (typeof ref === 'undefined') {
|
||||
worldReq
|
||||
.getWorld(params)
|
||||
.then((args) => {
|
||||
args.ref = worldStore.applyWorld(args.json);
|
||||
resolve(args);
|
||||
})
|
||||
.catch(reject);
|
||||
} else {
|
||||
resolve({
|
||||
cache: true,
|
||||
json: ref,
|
||||
params,
|
||||
ref
|
||||
});
|
||||
}
|
||||
});
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.world(params.worldId),
|
||||
policy: entityQueryPolicies.world,
|
||||
queryFn: () => worldReq.getWorld(params)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -70,6 +64,24 @@ const worldReq = {
|
||||
return args;
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @param {object} params
|
||||
* @param {string} [option]
|
||||
* @returns {Promise<{json: any, cache?: boolean, params: any, option?: string}>}
|
||||
*/
|
||||
getCachedWorlds(params, option) {
|
||||
return fetchWithEntityPolicy({
|
||||
queryKey: queryKeys.worldsByUser({
|
||||
...params,
|
||||
option: option || ''
|
||||
}),
|
||||
policy: entityQueryPolicies.worldCollection,
|
||||
queryFn: () => worldReq.getWorlds(params, option)
|
||||
}).then(({ data, cache }) => ({
|
||||
...data,
|
||||
cache
|
||||
}));
|
||||
},
|
||||
/**
|
||||
* @param {{worldId: string}} params
|
||||
* @returns {Promise<{json: any, params}>}
|
||||
@@ -100,6 +112,12 @@ const worldReq = {
|
||||
params
|
||||
};
|
||||
args.ref = worldStore.applyWorld(json);
|
||||
patchAndRefetchActiveQuery({
|
||||
queryKey: queryKeys.world(args.ref.id),
|
||||
nextData: args
|
||||
}).catch((err) => {
|
||||
console.error('Failed to refresh world query after mutation:', err);
|
||||
});
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -119,6 +137,12 @@ const worldReq = {
|
||||
params
|
||||
};
|
||||
args.ref = worldStore.applyWorld(json);
|
||||
patchAndRefetchActiveQuery({
|
||||
queryKey: queryKeys.world(args.ref.id),
|
||||
nextData: args
|
||||
}).catch((err) => {
|
||||
console.error('Failed to refresh world query after publish:', err);
|
||||
});
|
||||
return args;
|
||||
});
|
||||
},
|
||||
@@ -138,6 +162,12 @@ const worldReq = {
|
||||
params
|
||||
};
|
||||
args.ref = worldStore.applyWorld(json);
|
||||
patchAndRefetchActiveQuery({
|
||||
queryKey: queryKeys.world(args.ref.id),
|
||||
nextData: args
|
||||
}).catch((err) => {
|
||||
console.error('Failed to refresh world query after unpublish:', err);
|
||||
});
|
||||
return args;
|
||||
});
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user