Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 20 additions & 19 deletions apps/events/src/components/todos2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ export const Todos2 = () => {
data: dataTodos,
isLoading: isLoadingTodos,
isError: isErrorTodos,
preparePublish: preparePublishTodos,
} = useQuery(Todo2, { include: { assignees: {} } });
// preparePublish: preparePublishTodos,
} = useQuery(Todo2, { mode: 'private', include: { assignees: {} } });
const {
data: dataUsers,
isLoading: isLoadingUsers,
isError: isErrorUsers,
preparePublish: preparePublishUsers,
} = useQuery(User);
// preparePublish: preparePublishUsers,
} = useQuery(User, { mode: 'private' });
const space = useHypergraphSpace();
const createTodo = useCreateEntity(Todo2);
const updateTodo = useUpdateEntity(Todo2);
Expand Down Expand Up @@ -178,22 +178,22 @@ export const Todos2 = () => {
onClick={async () => {
try {
setIsPreparingPublish(true);
const usersResult = await preparePublishUsers();
console.log('users ops & diff', usersResult);
const todosResult = await preparePublishTodos();
console.log('todos ops & diff', todosResult);
// const usersResult = await preparePublishUsers();
// console.log('users ops & diff', usersResult);
// const todosResult = await preparePublishTodos();
// console.log('todos ops & diff', todosResult);

if (todosResult && usersResult) {
setPublishData({
newEntities: [...todosResult.newEntities, ...usersResult.newEntities],
deletedEntities: [...todosResult.deletedEntities, ...usersResult.deletedEntities],
updatedEntities: [...todosResult.updatedEntities, ...usersResult.updatedEntities],
});
setIsPublishDiffModalOpen(true);
} else {
console.error('preparing publishing error', todosResult, usersResult);
throw new Error('Failed to prepare the publishing operations');
}
// if (todosResult && usersResult) {
// setPublishData({
// newEntities: [...todosResult.newEntities, ...usersResult.newEntities],
// deletedEntities: [...todosResult.deletedEntities, ...usersResult.deletedEntities],
// updatedEntities: [...todosResult.updatedEntities, ...usersResult.updatedEntities],
// });
// setIsPublishDiffModalOpen(true);
// } else {
// console.error('preparing publishing error', todosResult, usersResult);
// throw new Error('Failed to prepare the publishing operations');
// }
} catch (error) {
console.error('preparing publishing error', error);
alert('Failed to prepare the publishing operations');
Expand Down Expand Up @@ -229,6 +229,7 @@ export const Todos2 = () => {
].flat();
const publishOpsResult = await publishOps({
ops,
// @ts-expect-error - TODO: fix the types error
walletClient: smartAccountWalletClient,
space,
name: 'Update users and todos',
Expand Down
2 changes: 1 addition & 1 deletion apps/events/src/components/users/users-merged.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Spinner } from '../spinner';
import { Button } from '../ui/button';

export const UsersMerged = () => {
const { data, isLoading, isError } = useQuery(User);
const { data, isLoading, isError } = useQuery(User, { mode: 'private' });
const deleteEntity = useDeleteEntity();

return (
Expand Down
141 changes: 68 additions & 73 deletions packages/hypergraph-react/src/use-query.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import { type Entity, Type, Utils, store } from '@graphprotocol/hypergraph';
import { useSelector } from '@xstate/store/react';
import { type Entity, Type, Utils } from '@graphprotocol/hypergraph';
import type * as Schema from 'effect/Schema';
import { useMemo } from 'react';
import { useQueryLocal } from './HypergraphSpaceContext.js';
import { generateDeleteOps } from './internal/generate-delete-ops.js';
import { useGenerateCreateOps } from './internal/use-generate-create-ops.js';
import { useGenerateUpdateOps } from './internal/use-generate-update-ops.js';
import { parseResult, useQueryPublic } from './internal/use-query-public.js';
import type { DiffEntry, PublishDiffInfo } from './types.js';
import { useQueryPublic } from './internal/use-query-public.js';
import type { DiffEntry } from './types.js';

type QueryParams<S extends Entity.AnyNoContext> = {
mode?: 'merged' | 'public' | 'private';
mode: 'public' | 'private';
filter?: { [K in keyof Schema.Schema.Type<S>]?: Entity.EntityFieldFilter<Schema.Schema.Type<S>[K]> } | undefined;
// TODO: for multi-level nesting it should only allow the allowed properties instead of Record<string, Record<string, never>>
include?: { [K in keyof Schema.Schema.Type<S>]?: Record<string, Record<string, never>> } | undefined;
};

// @ts-expect-error TODO: remove this function
const mergeEntities = <S extends Entity.AnyNoContext>(
publicEntities: Entity.Entity<S>[],
localEntities: Entity.Entity<S>[],
Expand Down Expand Up @@ -47,6 +43,7 @@ const mergeEntities = <S extends Entity.AnyNoContext>(
return mergedData;
};

// @ts-expect-error TODO: remove this function
const getDiff = <S extends Entity.AnyNoContext>(
type: S,
publicEntities: Entity.Entity<S>[],
Expand Down Expand Up @@ -145,20 +142,20 @@ const getDiff = <S extends Entity.AnyNoContext>(

const preparePublishDummy = () => undefined;

export function useQuery<const S extends Entity.AnyNoContext>(type: S, params?: QueryParams<S>) {
const { mode = 'merged', filter, include } = params ?? {};
const publicResult = useQueryPublic(type, { enabled: mode === 'public' || mode === 'merged', include });
const localResult = useQueryLocal(type, { enabled: mode === 'private' || mode === 'merged', filter, include });
const mapping = useSelector(store, (state) => state.context.mapping);
const generateCreateOps = useGenerateCreateOps(type, mode === 'merged');
const generateUpdateOps = useGenerateUpdateOps(type, mode === 'merged');

const mergedData = useMemo(() => {
if (mode !== 'merged' || publicResult.isLoading) {
return localResult.entities;
}
return mergeEntities(publicResult.data, localResult.entities, localResult.deletedEntities);
}, [mode, publicResult.isLoading, publicResult.data, localResult.entities, localResult.deletedEntities]);
export function useQuery<const S extends Entity.AnyNoContext>(type: S, params: QueryParams<S>) {
const { mode, filter, include } = params;
const publicResult = useQueryPublic(type, { enabled: mode === 'public', include });
const localResult = useQueryLocal(type, { enabled: mode === 'private', filter, include });
// const mapping = useSelector(store, (state) => state.context.mapping);
// const generateCreateOps = useGenerateCreateOps(type, mode === 'merged');
// const generateUpdateOps = useGenerateUpdateOps(type, mode === 'merged');

// const mergedData = useMemo(() => {
// if (mode !== 'merged' || publicResult.isLoading) {
// return localResult.entities;
// }
// return mergeEntities(publicResult.data, localResult.entities, localResult.deletedEntities);
// }, [mode, publicResult.isLoading, publicResult.data, localResult.entities, localResult.deletedEntities]);

if (mode === 'public') {
return {
Expand All @@ -168,58 +165,56 @@ export function useQuery<const S extends Entity.AnyNoContext>(type: S, params?:
};
}

if (mode === 'private') {
return {
...publicResult,
data: localResult.entities,
deleted: localResult.deletedEntities,
preparePublish: preparePublishDummy,
};
}

const preparePublish = async (): Promise<PublishDiffInfo> => {
// @ts-expect-error TODO should use the actual type instead of the name in the mapping
const typeName = type.name;
const mappingEntry = mapping?.[typeName];
if (!mappingEntry) {
throw new Error(`Mapping entry for ${typeName} not found`);
}

const result = await publicResult.refetch();
if (!result.data) {
throw new Error('No data found');
}
const diff = getDiff(
type,
parseResult(result.data, type, mappingEntry, mapping).data,
localResult.entities,
localResult.deletedEntities,
);

const newEntities = diff.newEntities.map((entity) => {
const { ops: createOps } = generateCreateOps(entity);
return { id: entity.id, entity, ops: createOps };
});

const updatedEntities = diff.updatedEntities.map((updatedEntityInfo) => {
const { ops: updateOps } = generateUpdateOps({ id: updatedEntityInfo.id, diff: updatedEntityInfo.diff });
return { ...updatedEntityInfo, ops: updateOps };
});

const deletedEntities = await Promise.all(
diff.deletedEntities.map(async (entity) => {
const deleteOps = await generateDeleteOps(entity);
return { id: entity.id, entity, ops: deleteOps };
}),
);

return { newEntities, updatedEntities, deletedEntities };
};

return {
...publicResult,
data: mergedData,
data: localResult.entities,
deleted: localResult.deletedEntities,
preparePublish: !publicResult.isLoading ? preparePublish : preparePublishDummy,
preparePublish: preparePublishDummy,
};

// const preparePublish = async (): Promise<PublishDiffInfo> => {
// // @ts-expect-error TODO should use the actual type instead of the name in the mapping
// const typeName = type.name;
// const mappingEntry = mapping?.[typeName];
// if (!mappingEntry) {
// throw new Error(`Mapping entry for ${typeName} not found`);
// }

// const result = await publicResult.refetch();
// if (!result.data) {
// throw new Error('No data found');
// }
// const diff = getDiff(
// type,
// parseResult(result.data, type, mappingEntry, mapping).data,
// localResult.entities,
// localResult.deletedEntities,
// );

// const newEntities = diff.newEntities.map((entity) => {
// const { ops: createOps } = generateCreateOps(entity);
// return { id: entity.id, entity, ops: createOps };
// });

// const updatedEntities = diff.updatedEntities.map((updatedEntityInfo) => {
// const { ops: updateOps } = generateUpdateOps({ id: updatedEntityInfo.id, diff: updatedEntityInfo.diff });
// return { ...updatedEntityInfo, ops: updateOps };
// });

// const deletedEntities = await Promise.all(
// diff.deletedEntities.map(async (entity) => {
// const deleteOps = await generateDeleteOps(entity);
// return { id: entity.id, entity, ops: deleteOps };
// }),
// );

// return { newEntities, updatedEntities, deletedEntities };
// };

// return {
// ...publicResult,
// data: mergedData,
// deleted: localResult.deletedEntities,
// preparePublish: !publicResult.isLoading ? preparePublish : preparePublishDummy,
// };
}
Loading