Skip to content

Commit edf7630

Browse files
authored
Schema improvements (#545)
1 parent 614c691 commit edf7630

File tree

92 files changed

+1699
-2728
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+1699
-2728
lines changed

.changeset/icy-emus-tap.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
"create-hypergraph": minor
3+
"@graphprotocol/hypergraph-react": minor
4+
"@graphprotocol/hypergraph": minor
5+
---
6+
7+
Schema Definition API Change (Breaking Change)
8+
9+
Before:
10+
```ts
11+
export class User extends Entity.Class<User>('User')({
12+
name: Type.String,
13+
}) {}
14+
```
15+
16+
After:
17+
```ts
18+
export const User = EntitySchema(
19+
{ name: Type.String },
20+
{
21+
types: [Id('bffa181e-a333-495b-949c-57f2831d7eca')],
22+
properties: {
23+
name: Id('a126ca53-0c8e-48d5-b888-82c734c38935'),
24+
},
25+
},
26+
);
27+
```
28+
29+
All entity definitions need to be rewritten. The new API requires explicit type IDs and property IDs.

apps/events/src/Boot.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { HypergraphAppProvider } from '@graphprotocol/hypergraph-react';
22
import { createRouter, RouterProvider } from '@tanstack/react-router';
3-
import { mapping } from './mapping.js';
43
import { routeTree } from './routeTree.gen';
54

65
// Create a new router instance
@@ -15,11 +14,7 @@ declare module '@tanstack/react-router' {
1514

1615
export function Boot() {
1716
return (
18-
<HypergraphAppProvider
19-
syncServerUri="http://localhost:3030"
20-
mapping={mapping}
21-
appId="93bb8907-085a-4a0e-83dd-62b0dc98e793"
22-
>
17+
<HypergraphAppProvider syncServerUri="http://localhost:3030" appId="93bb8907-085a-4a0e-83dd-62b0dc98e793">
2318
<RouterProvider router={router} />
2419
</HypergraphAppProvider>
2520
);

apps/events/src/components/event.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const Event = ({ spaceId, entityId }: { spaceId: string; entityId: string
1313
space: spaceId,
1414
});
1515

16-
console.log({ component: 'Event', isPending, isError, data });
16+
// console.log({ component: 'Event', isPending, isError, data });
1717

1818
return (
1919
<div>

apps/events/src/components/events/events.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { Entity } from '@graphprotocol/hypergraph';
12
import {
23
preparePublish,
34
publishOps,
@@ -19,7 +20,7 @@ export const Events = () => {
1920
const { data: spaces } = useSpaces({ mode: 'public' });
2021
const [selectedSpace, setSelectedSpace] = useState<string>('');
2122

22-
const handlePublish = async (event: Event) => {
23+
const handlePublish = async (event: Entity.Entity<typeof Event>) => {
2324
if (!selectedSpace) {
2425
alert('No space selected');
2526
return;

apps/events/src/components/playground.tsx

Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,37 @@
1-
import {
2-
_useCreateEntityPublic,
3-
_useDeleteEntityPublic,
4-
useHypergraphApp,
5-
useQuery,
6-
useSpace,
7-
} from '@graphprotocol/hypergraph-react';
1+
import { _useDeleteEntityPublic, useHypergraphApp, useQuery, useSpace } from '@graphprotocol/hypergraph-react';
82
import { useState } from 'react';
93
import { Event } from '../schema';
104
import { Button } from './ui/button';
115

126
export const Playground = ({ spaceId }: { spaceId: string }) => {
13-
const { data, isLoading, isError } = useQuery(Event, {
7+
const { data, isLoading, isError, invalidEntities } = useQuery(Event, {
148
mode: 'public',
159
include: {
1610
sponsors: {
1711
jobOffers: {},
1812
},
1913
},
20-
// filter: {
21-
// or: [{ name: { startsWith: 'test' } }, { name: { startsWith: 'ETH' } }],
22-
// },
14+
filter: {
15+
or: [{ name: { startsWith: 'My' } }, { name: { startsWith: 'ETH' } }],
16+
},
17+
// filter: { name: { startsWith: 'My Test Event' } },
2318
first: 100,
2419
space: spaceId,
2520
});
2621
const [isDeleting, setIsDeleting] = useState(false);
27-
const [isCreating, setIsCreating] = useState(false);
2822
const { getSmartSessionClient } = useHypergraphApp();
2923

3024
const { name } = useSpace({ mode: 'public', space: spaceId });
3125

3226
const deleteEntity = _useDeleteEntityPublic(Event, { space: spaceId });
33-
const createEntity = _useCreateEntityPublic(Event, { space: spaceId });
3427

35-
console.log({ isLoading, isError, data });
28+
console.log({ isLoading, isError, data, invalidEntities });
3629

3730
return (
3831
<div>
3932
<h2 className="text-lg font-bold">Space: {name}</h2>
4033
{isLoading && <div>Loading...</div>}
4134
{isError && <div>Error</div>}
42-
<Button
43-
disabled={isCreating}
44-
onClick={async () => {
45-
setIsCreating(true);
46-
const walletClient = await getSmartSessionClient();
47-
if (!walletClient) {
48-
alert('Wallet client not found');
49-
setIsCreating(false);
50-
return;
51-
}
52-
const { success, cid, txResult } = await createEntity(
53-
{
54-
name: 'Test Event 42 by Nik',
55-
sponsors: [],
56-
},
57-
{ walletClient },
58-
);
59-
console.log('created', { success, cid, txResult });
60-
setIsCreating(false);
61-
}}
62-
>
63-
Create
64-
</Button>
6535
{data?.map((event) => (
6636
<div key={event.id}>
6737
<h2>{event.name}</h2>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { useQuery } from '@graphprotocol/hypergraph-react';
2+
import { Project } from '../schema';
3+
4+
export const Projects = ({ spaceId }: { spaceId: string }) => {
5+
const { data, isLoading, isError } = useQuery(Project, {
6+
mode: 'public',
7+
// include: {
8+
// sponsors: {
9+
// jobOffers: {},
10+
// },
11+
// },
12+
// filter: {
13+
// or: [{ name: { startsWith: 'test' } }, { name: { startsWith: 'ETH' } }],
14+
// },
15+
first: 100,
16+
space: spaceId,
17+
});
18+
console.log({ isLoading, isError, data });
19+
20+
return (
21+
<div>
22+
<h2 className="text-lg font-bold">Projects</h2>
23+
{isLoading && <div>Loading...</div>}
24+
{isError && <div>Error</div>}
25+
{data?.map((project) => (
26+
<div key={project.id}>
27+
<h2>{project.name}</h2>
28+
<pre className="text-xs">{JSON.stringify(project, null, 2)}</pre>
29+
</div>
30+
))}
31+
</div>
32+
);
33+
};

apps/events/src/components/todo/todos-local.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ export const TodosLocal = () => {
3030
/>
3131
{/* @ts-expect-error */}
3232
<div className="text-xs">{todo.__deleted ? 'deleted' : 'not deleted'}</div>
33-
{/* @ts-expect-error */}
34-
<div className="text-xs">{todo.__version}</div>
3533
<Button variant="secondary" size="sm" onClick={() => hardDeleteEntity(todo.id)}>
3634
Hard Delete
3735
</Button>

apps/events/src/components/todos2.tsx

Lines changed: 2 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,4 @@
1-
import type { PublishDiffInfo } from '@graphprotocol/hypergraph-react';
2-
import {
3-
PublishDiff,
4-
publishOps,
5-
useCreateEntity,
6-
useDeleteEntity,
7-
useHypergraphApp,
8-
useQuery,
9-
useSpace,
10-
useUpdateEntity,
11-
} from '@graphprotocol/hypergraph-react';
12-
import { useQueryClient } from '@tanstack/react-query';
1+
import { useCreateEntity, useDeleteEntity, useQuery, useSpace, useUpdateEntity } from '@graphprotocol/hypergraph-react';
132
import { useEffect, useState } from 'react';
143
import Select from 'react-select';
154
import { cn } from '@/lib/utils';
@@ -19,7 +8,6 @@ import { TodosLocal } from './todo/todos-local';
198
import { TodosPublic } from './todo/todos-public';
209
import { Button } from './ui/button';
2110
import { Input } from './ui/input';
22-
import { Modal } from './ui/modal';
2311

2412
export const Todos2 = () => {
2513
const {
@@ -34,20 +22,14 @@ export const Todos2 = () => {
3422
isError: isErrorUsers,
3523
// preparePublish: preparePublishUsers,
3624
} = useQuery(User, { mode: 'private' });
37-
const { ready: spaceReady, id: spaceId } = useSpace({ mode: 'private' });
38-
const { getSmartSessionClient } = useHypergraphApp();
25+
const { ready: spaceReady } = useSpace({ mode: 'private' });
3926
const createTodo = useCreateEntity(Todo2);
4027
const updateTodo = useUpdateEntity(Todo2);
4128
const createUser = useCreateEntity(User);
4229
const deleteEntity = useDeleteEntity();
4330
const [newTodoName, setNewTodoName] = useState('');
4431
const [newTodoAssignees, setNewTodoAssignees] = useState<{ value: string; label: string }[]>([]);
4532
const [newUserName, setNewUserName] = useState('');
46-
const queryClient = useQueryClient();
47-
const [publishData, setPublishData] = useState<PublishDiffInfo | null>(null);
48-
const [isPublishDiffModalOpen, setIsPublishDiffModalOpen] = useState(false);
49-
const [isPreparingPublish, setIsPreparingPublish] = useState(false);
50-
const [isPublishing, setIsPublishing] = useState(false);
5133

5234
useEffect(() => {
5335
setNewTodoAssignees((prevFilteredAssignees) => {
@@ -74,8 +56,6 @@ export const Todos2 = () => {
7456
<div key={user.id} className="flex flex-row items-center gap-2">
7557
<h2>{user.name}</h2>
7658
<div className="text-xs">{user.id}</div>
77-
{/* @ts-expect-error */}
78-
<div className="text-xs">{user.__version}</div>
7959
<Button variant="outline" size="sm" onClick={() => deleteEntity(user.id)}>
8060
Delete
8161
</Button>
@@ -140,8 +120,6 @@ export const Todos2 = () => {
140120
))}
141121
</span>
142122
)}
143-
{/* @ts-expect-error */}
144-
<div className="text-xs">{todo.__version}</div>
145123
<Button variant="outline" size="sm" onClick={() => deleteEntity(todo.id)}>
146124
Delete
147125
</Button>
@@ -179,92 +157,6 @@ export const Todos2 = () => {
179157
</Button>
180158
</div>
181159

182-
<Button
183-
onClick={async () => {
184-
try {
185-
setIsPreparingPublish(true);
186-
// const usersResult = await preparePublishUsers();
187-
// console.log('users ops & diff', usersResult);
188-
// const todosResult = await preparePublishTodos();
189-
// console.log('todos ops & diff', todosResult);
190-
191-
// if (todosResult && usersResult) {
192-
// setPublishData({
193-
// newEntities: [...todosResult.newEntities, ...usersResult.newEntities],
194-
// deletedEntities: [...todosResult.deletedEntities, ...usersResult.deletedEntities],
195-
// updatedEntities: [...todosResult.updatedEntities, ...usersResult.updatedEntities],
196-
// });
197-
// setIsPublishDiffModalOpen(true);
198-
// } else {
199-
// console.error('preparing publishing error', todosResult, usersResult);
200-
// throw new Error('Failed to prepare the publishing operations');
201-
// }
202-
} catch (error) {
203-
console.error('preparing publishing error', error);
204-
alert('Failed to prepare the publishing operations');
205-
} finally {
206-
setIsPreparingPublish(false);
207-
}
208-
}}
209-
disabled={isPreparingPublish}
210-
>
211-
{isPreparingPublish ? 'Preparing …' : 'Prepare Publish'}
212-
</Button>
213-
214-
<Modal isOpen={isPublishDiffModalOpen} onOpenChange={setIsPublishDiffModalOpen}>
215-
<div className="p-4 flex flex-col gap-4 min-w-96">
216-
<PublishDiff
217-
newEntities={publishData?.newEntities ?? []}
218-
deletedEntities={publishData?.deletedEntities ?? []}
219-
updatedEntities={publishData?.updatedEntities ?? []}
220-
/>
221-
<Button
222-
onClick={async () => {
223-
try {
224-
const smartSessionClient = await getSmartSessionClient();
225-
if (!smartSessionClient) {
226-
throw new Error('Missing smartSessionClient');
227-
}
228-
if (publishData) {
229-
setIsPublishing(true);
230-
const ops = [
231-
...publishData.newEntities.map((entity) => entity.ops),
232-
...publishData.updatedEntities.map((entity) => entity.ops),
233-
...publishData.deletedEntities.map((entity) => entity.ops),
234-
].flat();
235-
const publishOpsResult = await publishOps({
236-
ops,
237-
walletClient: smartSessionClient,
238-
space: spaceId,
239-
name: 'Update users and todos',
240-
});
241-
console.log('publishOpsResult', publishOpsResult);
242-
setIsPublishDiffModalOpen(false);
243-
setPublishData(null);
244-
setTimeout(() => {
245-
queryClient.invalidateQueries({
246-
queryKey: ['hypergraph-public-entities', Todo2.name],
247-
});
248-
}, 1000);
249-
}
250-
} catch (error) {
251-
console.error('publishing error', error);
252-
} finally {
253-
setIsPublishing(false);
254-
}
255-
}}
256-
disabled={
257-
(publishData?.newEntities.length === 0 &&
258-
publishData?.updatedEntities.length === 0 &&
259-
publishData?.deletedEntities.length === 0) ||
260-
isPublishing
261-
}
262-
>
263-
{isPublishing ? 'Publishing …' : 'Publish'}
264-
</Button>
265-
</div>
266-
</Modal>
267-
268160
<TodosLocal />
269161

270162
<TodosPublic />

apps/events/src/components/user-entry.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
import type { Entity } from '@graphprotocol/hypergraph';
12
import { useDeleteEntity, useUpdateEntity } from '@graphprotocol/hypergraph-react';
23
import { useState } from 'react';
34
import { User } from '../schema.js';
45
import { Button } from './ui/button';
56
import { Input } from './ui/input.js';
67

7-
export const UserEntry = (user: User & { id: string }) => {
8+
export const UserEntry = (user: Entity.Entity<typeof User> & { id: string }) => {
89
const deleteEntity = useDeleteEntity();
910
const updateEntity = useUpdateEntity(User);
1011
const [editMode, setEditMode] = useState(false);

apps/events/src/components/users.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { UserEntry } from './user-entry.js';
88
export const Users = () => {
99
const { data: users } = useQuery(User, { mode: 'private' });
1010
const { ready: spaceReady } = useSpace({ mode: 'private' });
11-
const createEntity = useCreateEntity(User);
11+
const createEntityNew = useCreateEntity(User);
1212
const [newUserName, setNewUserName] = useState('');
1313

1414
if (!spaceReady) {
@@ -22,7 +22,7 @@ export const Users = () => {
2222
<Input type="text" value={newUserName} onChange={(e) => setNewUserName(e.target.value)} />
2323
<Button
2424
onClick={() => {
25-
createEntity({ name: newUserName });
25+
createEntityNew({ name: newUserName });
2626
setNewUserName('');
2727
}}
2828
>

0 commit comments

Comments
 (0)