Skip to content

Commit 77c0d14

Browse files
authored
Merge pull request #149 from hypercerts-org/fix/query_fractions_view
fix(resolver): claims and fractions nested queries
2 parents f069827 + 97d231b commit 77c0d14

File tree

7 files changed

+84
-153
lines changed

7 files changed

+84
-153
lines changed

src/graphql/schemas/resolvers/baseTypes.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,19 @@ export function createBaseResolver<T extends ClassType>(
103103
return queries.data.executeTakeFirst();
104104
}
105105

106+
console.log("got hypercerts queries: ", queries);
107+
106108
return this.supabaseCachingService.db
107109
.transaction()
108110
.execute(async (transaction) => {
111+
console.log("got transaction: ", transaction);
112+
console.log("got transaction execute query: ", queries.data);
109113
const dataRes = await transaction.executeQuery(queries.data);
114+
115+
console.log("got hypercerts data: ", dataRes);
110116
const countRes = await transaction.executeQuery(queries.count);
117+
118+
console.log("got hypercerts data and count: ", dataRes, countRes);
111119
return {
112120
data: dataRes.rows,
113121
count: countRes.rows[0].count,

src/graphql/schemas/resolvers/fractionResolver.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,21 @@ class FractionResolver extends FractionBaseResolver {
2424
}
2525

2626
@FieldResolver()
27-
async orders(@Root() fraction: Partial<Fraction>) {
27+
async metadata(@Root() fraction: Fraction) {
28+
if (!fraction.claims_id) {
29+
return;
30+
}
31+
32+
return await this.getMetadata(
33+
{
34+
where: { hypercerts: { id: { eq: fraction.claims_id } } },
35+
},
36+
true,
37+
);
38+
}
39+
40+
@FieldResolver()
41+
async orders(@Root() fraction: Fraction) {
2842
if (!fraction.fraction_id) {
2943
return null;
3044
}
@@ -71,21 +85,7 @@ class FractionResolver extends FractionBaseResolver {
7185
}
7286

7387
@FieldResolver()
74-
async metadata(@Root() fraction: Partial<Fraction>) {
75-
if (!fraction.claims_id) {
76-
return;
77-
}
78-
79-
return await this.getMetadata(
80-
{
81-
where: { hypercerts: { id: { eq: fraction.claims_id } } },
82-
},
83-
true,
84-
);
85-
}
86-
87-
@FieldResolver()
88-
async sales(@Root() fraction: Partial<Fraction>) {
88+
async sales(@Root() fraction: Fraction) {
8989
if (!fraction.fraction_id) {
9090
return null;
9191
}

src/graphql/schemas/resolvers/hypercertResolver.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,9 @@ class HypercertResolver extends HypercertBaseResolver {
7373
return;
7474
}
7575

76-
return await this.getFractions(
77-
{ where: { hypercert_id: { eq: hypercert.hypercert_id } } },
78-
false,
79-
);
76+
return await this.getFractions({
77+
where: { hypercert_id: { eq: hypercert.hypercert_id } },
78+
});
8079
}
8180

8281
@FieldResolver()

src/graphql/schemas/typeDefs/fractionTypeDefs.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Fraction extends BasicTypeDef {
1717
description: "Address of the owner of the fractions",
1818
})
1919
owner_address?: string;
20+
2021
@Field(() => EthBigInt, {
2122
nullable: true,
2223
description: "Units held by the fraction",
@@ -43,6 +44,7 @@ class Fraction extends BasicTypeDef {
4344
description: "Marketplace orders related to this fraction",
4445
})
4546
orders?: GetOrdersResponse;
47+
4648
@Field(() => Metadata, {
4749
nullable: true,
4850
description: "The metadata for the fraction",

src/graphql/schemas/typeDefs/hypercertTypeDefs.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ class Hypercert extends HypercertBaseType {
3737
"Transferable fractions representing partial ownership of the hypercert",
3838
})
3939
fractions?: GetFractionsResponse;
40+
4041
@Field(() => GetAttestationsResponse, {
4142
nullable: true,
4243
description: "Attestations for the hypercert or parts of its data",
4344
})
4445
attestations?: GetAttestationsResponse;
46+
4547
@Field(() => GetOrdersForHypercertResponse, {
4648
nullable: true,
4749
description: "Marketplace orders related to this hypercert",
Lines changed: 32 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,128 +1,47 @@
1-
import {
2-
IdSearchOptions,
3-
NumberArraySearchOptions,
4-
NumberSearchOptions,
5-
StringArraySearchOptions,
6-
StringSearchOptions
7-
} from "../inputs/searchOptions.js";
8-
91
type OperandType = string | number | bigint | string[] | bigint[];
10-
type OperatorType = "eq" | "gt" | "gte" | "lt" | "lte" | "ilike" | "contains" | "startsWith" | "endsWith"
11-
12-
export const generateFilterValues = (column: string, operator: OperatorType, operand: OperandType) => {
13-
console.log("generateFilterValues", column, operator, operand);
2+
type OperatorType =
3+
| "eq"
4+
| "gt"
5+
| "gte"
6+
| "lt"
7+
| "lte"
8+
| "ilike"
9+
| "contains"
10+
| "startsWith"
11+
| "endsWith";
12+
13+
enum OperatorSymbols {
14+
eq = "=",
15+
gt = ">",
16+
gte = ">=",
17+
lt = "<",
18+
lte = "<=",
19+
ilike = "ilike",
20+
}
1421

22+
export const generateFilterValues = (
23+
column: string,
24+
operator: OperatorType,
25+
operand: OperandType,
26+
) => {
1527
switch (operator) {
1628
case "eq":
17-
return [column, "=", operand];
29+
return [column, OperatorSymbols.eq, operand];
1830
case "gt":
19-
return [column, ">", operand];
31+
return [column, OperatorSymbols.gt, operand];
2032
case "gte":
21-
return [column, ">=", operand];
33+
return [column, OperatorSymbols.gte, operand];
2234
case "lt":
23-
return [column, "<", operand];
35+
return [column, OperatorSymbols.lt, operand];
2436
case "lte":
25-
return [column, "<=", operand];
37+
return [column, OperatorSymbols.lte, operand];
2638
case "contains":
27-
return [column, "like", `%${operand}%`];
39+
return [column, OperatorSymbols.ilike, operand];
2840
case "startsWith":
29-
return [column, "like", `${operand}%`];
41+
return [column, OperatorSymbols.ilike, operand];
3042
case "endsWith":
31-
return [column, "like", `%${operand}`];
32-
}
33-
34-
return [];
35-
};
36-
37-
38-
39-
const generateArrayFilters = (value: NumberArraySearchOptions | StringArraySearchOptions, column: string) => {
40-
const filters: [OperatorType, string, OperandType][] = [];
41-
for (const [operator, operand] of Object.entries(value)) {
42-
if (!operand) continue;
43-
44-
// Assert operand is an array of numbers
45-
if (!Array.isArray(operand)) {
46-
throw new Error(`Expected operand to be an array, but got ${typeof operand}`);
47-
}
48-
49-
switch (operator) {
50-
case "contains":
51-
filters.push(["contains", column, operand]);
52-
break;
53-
}
54-
}
55-
return filters;
56-
};
57-
58-
function isStringSearchOptions(value: unknown): value is StringSearchOptions {
59-
if (typeof value !== "object" || value === null) {
60-
return false;
61-
}
62-
63-
const possibleStringSearchOptions = value as Partial<StringSearchOptions>;
64-
65-
// Check for properties unique to StringSearchOptions
66-
const keys = ["eq", "contains", "startsWith", "endsWith"];
67-
return keys.some(key => key in possibleStringSearchOptions);
68-
}
69-
70-
function isNumberSearchOptions(value: unknown): value is NumberSearchOptions {
71-
if (typeof value !== "object" || value === null) {
72-
return false;
73-
}
74-
75-
const possibleNumberSearchOptions = value as Partial<NumberSearchOptions>;
76-
77-
// Check for properties unique to NumberSearchOptions
78-
const keys = ["eq", "gt", "gte", "lt", "lte"];
79-
return keys.some(key => key in possibleNumberSearchOptions);
80-
}
81-
82-
function isIdSearchOptions(value: unknown): value is IdSearchOptions {
83-
if (typeof value !== "object" || value === null) {
84-
return false;
85-
}
86-
87-
const possibleIdSearchOptions = value as Partial<NumberSearchOptions>;
88-
89-
// Check for properties unique to IdSearchOptions
90-
const keys = ["eq", "contains", "startsWith", "endsWith"];
91-
return keys.some(key => key in possibleIdSearchOptions);
92-
93-
}
94-
95-
function isStringArraySearchOptions(value: unknown): value is StringArraySearchOptions {
96-
if (!Array.isArray(value) || value === null) {
97-
return false;
98-
}
99-
100-
const possibleStringArraySearchOptions = value as Partial<StringArraySearchOptions>;
101-
102-
// Check for properties unique to StringArraySearchOptions
103-
const keys = ["contains"];
104-
return keys.some(key => key in possibleStringArraySearchOptions);
105-
}
106-
107-
function isNumberArraySearchOptions(value: unknown): value is NumberArraySearchOptions {
108-
if (!Array.isArray(value) || value === null) {
109-
return false;
110-
}
111-
112-
const possibleNumberArraySearchOptions = value as Partial<NumberArraySearchOptions>;
113-
114-
// Check for properties unique to NumberArraySearchOptions
115-
const keys = ["contains"];
116-
return keys.some(key => key in possibleNumberArraySearchOptions);
117-
}
118-
119-
const buildFilters = (value: unknown, column: string) => {
120-
121-
if (isStringArraySearchOptions(value) || isNumberArraySearchOptions(value)) {
122-
return generateArrayFilters(value, column);
43+
return [column, OperatorSymbols.ilike, operand];
12344
}
12445

12546
return [];
12647
};
127-
128-

src/services/SupabaseCachingService.ts

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -110,33 +110,28 @@ export class SupabaseCachingService {
110110
case "claims":
111111
return this.db
112112
.selectFrom("claims")
113-
.selectAll("claims") // Select all columns from the claims table
114113
.$if(args.where?.metadata, (qb) =>
115114
qb.innerJoin("metadata", "metadata.uri", "claims.uri"),
116115
)
117116
.$if(args.where?.attestations, (qb) =>
118117
qb.innerJoin("attestations", "attestations.claims_id", "claims.id"),
119118
)
120119
.$if(args.where?.fractions, (qb) =>
121-
qb.innerJoin("fractions_view", (join) =>
122-
join.on("fractions_view.claims_id", "=", "claims.id"),
120+
qb.innerJoin(
121+
"fractions_view",
122+
"fractions_view.claims_id",
123+
"claims.id",
123124
),
124125
)
125126
.$if(args.where?.contract, (qb) =>
126127
qb.innerJoin("contracts", "contracts.id", "claims.contracts_id"),
127-
);
128+
)
129+
.selectAll(); // Select all columns from the claims table
128130
case "contracts":
129131
return this.db.selectFrom("contracts").selectAll();
130132
case "fractions":
131133
case "fractions_view":
132134
return this.db.selectFrom("fractions_view").selectAll();
133-
// .$if(args.where?.hypercerts, (qb) =>
134-
// qb.leftJoin(
135-
// "claims",
136-
// "claims.hypercert_id",
137-
// "fractions_view.hypercert_id",
138-
// ),
139-
// );
140135
case "metadata":
141136
return this.db
142137
.selectFrom("metadata")
@@ -193,7 +188,11 @@ export class SupabaseCachingService {
193188
qb.innerJoin("attestations", "attestations.claims_id", "claims.id"),
194189
)
195190
.$if(args.where?.fractions, (qb) =>
196-
qb.innerJoin("fractions", "fractions.claims_id", "claims.id"),
191+
qb.innerJoin(
192+
"fractions_view",
193+
"fractions_view.claims_id",
194+
"claims.id",
195+
),
197196
)
198197
.$if(args.where?.contract, (qb) =>
199198
qb.innerJoin("contracts", "contracts.id", "claims.contracts_id"),
@@ -245,8 +244,6 @@ export class SupabaseCachingService {
245244
) {
246245
let query = this.getDataQuery(tableName, args);
247246

248-
console.log("Building data query");
249-
250247
const { where, first, offset, sort } = args;
251248
const eb = expressionBuilder(query);
252249

@@ -281,17 +278,23 @@ export class SupabaseCachingService {
281278
_table = "contracts";
282279
}
283280

281+
if (column === "fractions") {
282+
_table = "fractions_view";
283+
}
284+
284285
const [_col, _symbol, _input] = generateFilterValues(
285286
`${_table}.${_column}`,
286287
operator,
287288
operand,
288289
);
290+
289291
filters.push(eb(_col, _symbol, _input));
290292
}
291293

292294
return filters.flat();
293295
});
294296
}
297+
295298
return column && value ? eb(column, "=", value) : [];
296299
}),
297300
),
@@ -315,8 +318,6 @@ export class SupabaseCachingService {
315318
if (first) query = query.limit(first);
316319
if (offset) query = query.offset(offset);
317320

318-
console.log("Built query", query);
319-
320321
return query;
321322
}
322323

@@ -333,8 +334,6 @@ export class SupabaseCachingService {
333334
) {
334335
let query = this.getCountQuery(tableName, args);
335336

336-
console.log("Building count query");
337-
338337
const { where } = args;
339338
const eb = expressionBuilder(query);
340339

@@ -369,6 +368,10 @@ export class SupabaseCachingService {
369368
_table = "contracts";
370369
}
371370

371+
if (column === "fractions") {
372+
_table = "fractions_view";
373+
}
374+
372375
const [_col, _symbol, _input] = generateFilterValues(
373376
`${_table}.${_column}`,
374377
operator,
@@ -386,8 +389,6 @@ export class SupabaseCachingService {
386389
);
387390
}
388391

389-
console.log("Built query", query);
390-
391392
return query;
392393
}
393394

0 commit comments

Comments
 (0)