Skip to content
Closed
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
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@
"@sentry/types": "^8.2.1",
"@swc/cli": "^0.3.12",
"@swc/core": "^1.4.15",
"@swc/helpers": "^0.5.15",
"@swc/jest": "^0.2.37",
"@types/better-sqlite3": "^7.6.12",
"@types/body-parser": "^1.19.5",
"@types/mime-types": "^2.1.4",
"@types/multer": "^1.4.12",
Expand All @@ -107,6 +110,7 @@
"@types/sinon": "^17.0.2",
"@types/swagger-ui-express": "^4.1.6",
"@vitest/coverage-v8": "^2.1.8",
"better-sqlite3": "^11.8.1",
"chai": "^5.0.0",
"chai-assertions-count": "^1.0.2",
"concurrently": "^8.2.2",
Expand All @@ -129,6 +133,7 @@
"typedoc": "^0.26.5",
"typescript": "5.5.3",
"typescript-eslint": "^7.7.0",
"unplugin-swc": "^1.5.1",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^2.1.8",
"vitest-mock-extended": "^2.0.2"
Expand Down
563 changes: 391 additions & 172 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

15 changes: 13 additions & 2 deletions src/__generated__/routes/routes.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 26 additions & 4 deletions src/__generated__/swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion src/graphql/schemas/args/baseArgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import { Field, ArgsType, ClassType, Int } from "type-graphql";
import { WhereOptions } from "../inputs/whereOptions.js";
import { OrderOptions } from "../inputs/orderOptions.js";

// TODO BaseArgs is never used. Create a builder function that returns a class with pagination and takes specific where and sort instances
export type BaseArgs<T extends object> = {
where?: WhereOptions<T>;
sort?: OrderOptions<T>;
first?: number;
offset?: number;
};

export function withPagination<TItem extends ClassType>(TItemClass: TItem) {
export function withPagination<TItem extends ClassType>(TItemClass: TItem): B {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused, where does B come from?

@ArgsType()
class withPaginationClass extends TItemClass {
@Field(() => Int, { nullable: true })
Expand Down
4 changes: 4 additions & 0 deletions src/graphql/schemas/inputs/whereOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import type { BasicFractionWhereInput } from "./fractionInput.js";
import type { BasicMetadataWhereInput } from "./metadataInput.js";
import type { BasicHypercertWhereArgs } from "./hypercertsInput.js";
import type { BasicSignatureRequestWhereInput } from "./signatureRequestInput.js";
import { BasicAttestationWhereInput } from "./attestationInput.js";
import { BasicAttestationSchemaWhereInput } from "./attestationSchemaInput.js";

export type WhereOptions<T extends object> = {
[P in keyof T]:
Expand All @@ -25,5 +27,7 @@ export type WhereOptions<T extends object> = {
| BasicContractWhereInput
| BasicFractionWhereInput
| BasicSignatureRequestWhereInput
| BasicAttestationWhereInput

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it difficult to know where in our code base we need to add which classes etc. Can we perhaps generate that somehow? If there was one file, that consolidated all the entities and their where-inputs and whatnot and we generate this type from there it would be a much better DX.

| BasicAttestationSchemaWhereInput
| null;
};
18 changes: 10 additions & 8 deletions src/graphql/schemas/resolvers/baseTypes.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { type ClassType, Field, Int, Resolver, ObjectType } from "type-graphql";
import { SupabaseDataService } from "../../../services/SupabaseDataService.js";
import { container } from "tsyringe";
import { type ClassType, Field, Int, ObjectType, Resolver } from "type-graphql";
import { SupabaseCachingService } from "../../../services/SupabaseCachingService.js";
import { GetMetadataArgs } from "../args/metadataArgs.js";
import { GetContractsArgs } from "../args/contractArgs.js";
import { GetFractionsArgs } from "../args/fractionArgs.js";
import { SupabaseDataService } from "../../../services/SupabaseDataService.js";
import { GetAllowlistRecordsArgs } from "../args/allowlistRecordArgs.js";
import { GetAttestationSchemasArgs } from "../args/attestationSchemaArgs.js";
import { GetAttestationsArgs } from "../args/attestationArgs.js";
import { GetAttestationSchemasArgs } from "../args/attestationSchemaArgs.js";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be cool to have an /args/index.ts that exports all args and we do

import QueryArgs from "../args";

in this file?

import { GetBlueprintArgs } from "../args/blueprintArgs.js";
import { GetContractsArgs } from "../args/contractArgs.js";
import { GetFractionsArgs } from "../args/fractionArgs.js";
import { GetHypercertsArgs } from "../args/hypercertsArgs.js";
import { GetMetadataArgs } from "../args/metadataArgs.js";
import { GetOrdersArgs } from "../args/orderArgs.js";
import { GetSalesArgs } from "../args/salesArgs.js";
import { GetUserArgs } from "../args/userArgs.js";
import { GetBlueprintArgs } from "../args/blueprintArgs.js";
import { GetSignatureRequestArgs } from "../args/signatureRequestArgs.js";
import { GetUserArgs } from "../args/userArgs.js";

export function DataResponse<TItem extends object>(
TItemClass: ClassType<TItem>,
Expand Down Expand Up @@ -256,6 +257,7 @@ export function createBaseResolver<T extends ClassType>(

try {
const queries = this.supabaseCachingService.getAttestations(args);

if (single) {
const res = await queries.data.executeTakeFirst();
return res ? this.parseAttestation(res) : null;
Expand Down
63 changes: 35 additions & 28 deletions src/services/BaseSupabaseService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,40 @@ import { expressionBuilder, Kysely, SqlBool } from "kysely";
import { BaseArgs } from "../graphql/schemas/args/baseArgs.js";
import { SortOrder } from "../graphql/schemas/enums/sortEnums.js";
import { buildWhereCondition } from "../graphql/schemas/utils/filters-kysely.js";
import { CachingDatabase } from "../types/kyselySupabaseCaching.js";
import { DataDatabase } from "../types/kyselySupabaseData.js";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be way out of scope for this PR, but generally, the names Caching Database and Data Database are a bit unwieldy and slightly confusing. Especially Data Database is making me twitch every time 😄 How about something like CoreData and ChainData? For me personally, Caching Database doesn't really tell me what I would find in there.

import { QueryStrategyFactory } from "./database/QueryBuilder.js";

export abstract class BaseSupabaseService<DB> {
protected db: Kysely<DB>;
export abstract class BaseSupabaseService<
DB extends CachingDatabase | DataDatabase,
> {
protected constructor(protected db: Kysely<DB>) {}

protected constructor(db: Kysely<DB>) {
this.db = db;
}

abstract getDataQuery<T extends keyof DB & string, A extends object>(
tableName: T,
args: BaseArgs<A>, // eslint-disable-next-line @typescript-eslint/no-explicit-any
): any;

abstract getCountQuery<T extends keyof DB & string, A extends object>(
protected getDataQuery<T extends keyof DB>(
tableName: T,
args: BaseArgs<A>, // eslint-disable-next-line @typescript-eslint/no-explicit-any
): any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
args: BaseArgs<any>,
) {
const strategy = QueryStrategyFactory.getStrategy<T, DB>(tableName);
return strategy.buildDataQuery(this.db, args);
}

handleGetData<T extends keyof DB & string, A extends object>(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
protected getCountQuery<T extends keyof DB, A extends BaseArgs<any>>(
tableName: T,
args: BaseArgs<A> & {
first?: number;
offset?: number;
},
args: A,
) {
const strategy = QueryStrategyFactory.getStrategy<T, DB>(tableName);
return strategy.buildCountQuery(this.db, args);
}

protected handleGetData<
T extends keyof DB,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
TRecord extends Record<string, any>,
>(tableName: T, args: BaseArgs<TRecord>) {
let query = this.getDataQuery(tableName, args);

const { where, first, offset, sort } = args;
const eb = expressionBuilder(query);

Expand All @@ -45,13 +53,11 @@ export abstract class BaseSupabaseService<DB> {
return query;
}

handleGetCount<T extends keyof DB & string, A extends object>(
tableName: T,
args: BaseArgs<A> & {
first?: number;
offset?: number;
},
) {
protected handleGetCount<
T extends keyof DB,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
TRecord extends Record<string, any>,
>(tableName: T, args: BaseArgs<TRecord>) {
let query = this.getCountQuery(tableName, args);

const { where } = args;
Expand All @@ -64,7 +70,8 @@ export abstract class BaseSupabaseService<DB> {
return query;
}

private applyWhereConditions<T extends string>(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private applyWhereConditions<T extends keyof DB>(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
query: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -75,7 +82,7 @@ export abstract class BaseSupabaseService<DB> {
) {
const conditions = Object.entries(where)
.map(([column, value]) =>
buildWhereCondition(column, value, tableName, eb),
buildWhereCondition(column, value, String(tableName), eb),
)
.filter(Boolean);

Expand Down
Loading