Skip to content

Commit a4898c4

Browse files
authored
add Entity.searchManyPublic (#549)
1 parent 887dbc3 commit a4898c4

3 files changed

Lines changed: 240 additions & 0 deletions

File tree

.changeset/neat-tires-tie.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@graphprotocol/hypergraph": patch
3+
"@graphprotocol/hypergraph-react": patch
4+
---
5+
6+
add Entity.searchManyPublic
7+

packages/hypergraph/src/entity/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ export * from './find-many-public.js';
55
export * from './findOne.js';
66
export * from './removeRelation.js';
77
export * from './schema.js';
8+
export * from './search-many-public.js';
89
export * from './types.js';
910
export * from './update.js';
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
import { Graph } from '@graphprotocol/grc-20';
2+
import { Constants, type Entity, Utils } from '@graphprotocol/hypergraph';
3+
import * as Option from 'effect/Option';
4+
import * as Schema from 'effect/Schema';
5+
import * as SchemaAST from 'effect/SchemaAST';
6+
import { gql, request } from 'graphql-request';
7+
import { parseResult } from './find-many-public.js';
8+
9+
export type SearchManyPublicParams<S extends Schema.Schema.AnyNoContext> = {
10+
query: string;
11+
filter?: Entity.EntityFilter<Schema.Schema.Type<S>> | undefined;
12+
// TODO: for multi-level nesting it should only allow the allowed properties instead of Record<string, Record<string, never>>
13+
include?: { [K in keyof Schema.Schema.Type<S>]?: Record<string, Record<string, never>> } | undefined;
14+
space: string | undefined;
15+
first?: number | undefined;
16+
};
17+
18+
const searchQueryDocumentLevel0 = gql`
19+
query search($query: String!, $spaceId: UUID!, $typeIds: [UUID!]!, $first: Int, $filter: EntityFilter!) {
20+
search(
21+
query: $query
22+
filter: { and: [{
23+
typeIds: {in: $typeIds},
24+
spaceIds: {in: [$spaceId]},
25+
}, $filter]}
26+
spaceId: $spaceId
27+
first: $first
28+
offset: 0
29+
) {
30+
id
31+
name
32+
valuesList(filter: {spaceId: {is: $spaceId}}) {
33+
propertyId
34+
string
35+
boolean
36+
number
37+
time
38+
point
39+
}
40+
}
41+
}
42+
`;
43+
44+
const searchQueryDocumentLevel1 = gql`
45+
query search($query: String!, $spaceId: UUID!, $typeIds: [UUID!]!, $relationTypeIdsLevel1: [UUID!]!, $first: Int, $filter: EntityFilter!) {
46+
search(
47+
query: $query
48+
filter: { and: [{
49+
typeIds: {in: $typeIds},
50+
spaceIds: {in: [$spaceId]},
51+
}, $filter]}
52+
spaceId: $spaceId
53+
first: $first
54+
offset: 0
55+
) {
56+
id
57+
name
58+
valuesList(filter: {spaceId: {is: $spaceId}}) {
59+
propertyId
60+
string
61+
boolean
62+
number
63+
time
64+
point
65+
}
66+
relationsList(
67+
filter: {spaceId: {is: $spaceId}, typeId:{ in: $relationTypeIdsLevel1}},
68+
) {
69+
id
70+
toEntity {
71+
id
72+
name
73+
valuesList(filter: {spaceId: {is: $spaceId}}) {
74+
propertyId
75+
string
76+
boolean
77+
number
78+
time
79+
point
80+
}
81+
}
82+
typeId
83+
}
84+
}
85+
}
86+
`;
87+
88+
const searchQueryDocumentLevel2 = gql`
89+
query search($query: String!, $spaceId: UUID!, $typeIds: [UUID!]!, $relationTypeIdsLevel1: [UUID!]!, $relationTypeIdsLevel2: [UUID!]!, $first: Int, $filter: EntityFilter!) {
90+
search(
91+
query: $query
92+
filter: { and: [{
93+
typeIds: {in: $typeIds},
94+
spaceIds: {in: [$spaceId]},
95+
}, $filter]}
96+
spaceId: $spaceId
97+
first: $first
98+
offset: 0
99+
) {
100+
id
101+
name
102+
valuesList(filter: {spaceId: {is: $spaceId}}) {
103+
propertyId
104+
string
105+
boolean
106+
number
107+
time
108+
point
109+
}
110+
relationsList(
111+
filter: {spaceId: {is: $spaceId}, typeId:{ in: $relationTypeIdsLevel1}},
112+
) {
113+
id
114+
toEntity {
115+
id
116+
name
117+
valuesList(filter: {spaceId: {is: $spaceId}}) {
118+
propertyId
119+
string
120+
boolean
121+
number
122+
time
123+
point
124+
}
125+
relationsList(
126+
filter: {spaceId: {is: $spaceId}, typeId:{ in: $relationTypeIdsLevel2}},
127+
) {
128+
id
129+
toEntity {
130+
id
131+
name
132+
valuesList(filter: {spaceId: {is: $spaceId}}) {
133+
propertyId
134+
string
135+
boolean
136+
number
137+
time
138+
point
139+
}
140+
}
141+
typeId
142+
}
143+
}
144+
typeId
145+
}
146+
}
147+
}
148+
`;
149+
150+
type SearchQueryResult = {
151+
search: {
152+
id: string;
153+
name: string;
154+
valuesList: {
155+
propertyId: string;
156+
string: string;
157+
boolean: boolean;
158+
number: number;
159+
time: string;
160+
point: string;
161+
}[];
162+
relationsList: {
163+
id: string;
164+
toEntity: {
165+
id: string;
166+
name: string;
167+
valuesList: {
168+
propertyId: string;
169+
string: string;
170+
boolean: boolean;
171+
number: number;
172+
time: string;
173+
point: string;
174+
}[];
175+
relationsList: {
176+
id: string;
177+
toEntity: {
178+
id: string;
179+
name: string;
180+
valuesList: {
181+
propertyId: string;
182+
string: string;
183+
boolean: boolean;
184+
number: number;
185+
time: string;
186+
point: string;
187+
}[];
188+
};
189+
typeId: string;
190+
}[];
191+
};
192+
typeId: string;
193+
}[];
194+
}[];
195+
};
196+
197+
export const searchManyPublic = async <S extends Schema.Schema.AnyNoContext>(
198+
type: S,
199+
params?: SearchManyPublicParams<S>,
200+
) => {
201+
const { query, filter, include, space, first = 100 } = params ?? {};
202+
203+
// constructing the relation type ids for the query
204+
const relationTypeIds = Utils.getRelationTypeIds(type, include);
205+
206+
const typeIds = SchemaAST.getAnnotation<string[]>(Constants.TypeIdsSymbol)(type.ast as SchemaAST.TypeLiteral).pipe(
207+
Option.getOrElse(() => []),
208+
);
209+
210+
let queryDocument = searchQueryDocumentLevel0;
211+
if (relationTypeIds.level1.length > 0) {
212+
queryDocument = searchQueryDocumentLevel1;
213+
}
214+
if (relationTypeIds.level2.length > 0) {
215+
queryDocument = searchQueryDocumentLevel2;
216+
}
217+
218+
const filterParams = filter ? Utils.translateFilterToGraphql(filter, type) : {};
219+
220+
const result = await request<SearchQueryResult>(`${Graph.TESTNET_API_ORIGIN}/graphql`, queryDocument, {
221+
spaceId: space,
222+
typeIds,
223+
query,
224+
relationTypeIdsLevel1: relationTypeIds.level1,
225+
relationTypeIdsLevel2: relationTypeIds.level2,
226+
first,
227+
filter: filterParams,
228+
});
229+
230+
const { data, invalidEntities } = parseResult({ entities: result.search }, type);
231+
return { data, invalidEntities };
232+
};

0 commit comments

Comments
 (0)