UNPKG

@ensnode/ponder-subgraph

Version:

A Hono middleware for generating Subgraph-compatible GraphQL schema.

106 lines (100 loc) 3.66 kB
import { NodePgDatabase } from 'drizzle-orm/node-postgres'; import { PgliteDatabase } from 'drizzle-orm/pglite'; import DataLoader from 'dataloader'; import { TableRelationalConfig } from 'drizzle-orm'; import { TableConfig, PgTableExtraConfig, PgTable } from 'drizzle-orm/pg-core'; import { GraphQLSchema } from 'graphql'; type SubgraphMetaBlock = { /** Block number */ number: bigint; /** Block unix timestamp */ timestamp: bigint; /** Block hash */ hash: `0x${string}`; /** Block parent hash */ parentHash: `0x${string}`; }; /** * The metadata provider interface used to fetch data from the application layer. */ interface PonderMetadataProvider { /** * ENSIndexer app version. */ version: string; /** * Get last indexed block status * @returns The last indexed block status */ getLastIndexedDeploymentChainBlock(): Promise<SubgraphMetaBlock>; /** * Get the Ponder build ID * @returns The Ponder build ID */ getPonderBuildId(): Promise<string>; /** * Get the indexing errors status * @returns The indexing errors status */ hasIndexingErrors: () => Promise<boolean>; } /** * This is a graphql schema generated from a drizzle (sql) schema, initially based on ponder's. * https://github.com/ponder-sh/ponder/blob/main/packages/core/src/graphql/index.ts * * Its goal is to mimic the subgraph graphql api for queries we've deemed relevant (see docs). * * 1. inlines some ponder internal types * 2. implement subgraph's simpler offset pagination with first & skip w/out Page types * 3. PascalCase entity names * 4. Polymorphic Interfaces * 5. lower-case and/or filters * 6. relation id shorthand filters (i.e. domains(where: { owner_id: String })) * 7. sortable id columns * 8. temporarily ignores column normalization that was fixed in * https://github.com/ponder-sh/ponder/pull/1517/files */ type Drizzle<TSchema extends Schema = { [name: string]: never; }> = NodePgDatabase<TSchema> | PgliteDatabase<TSchema>; type Schema = { [name: string]: unknown; }; declare const onchain: unique symbol; type OnchainTable<T extends TableConfig & { extra: PgTableExtraConfig | undefined; } = TableConfig & { extra: PgTableExtraConfig | undefined; }> = PgTable<T> & { [Key in keyof T["columns"]]: T["columns"][Key]; } & { [onchain]: true; } & { enableRLS: () => Omit<OnchainTable<T>, "enableRLS">; }; /** * the following type describes: * 1. `types` — mapping a polymorphic type name to the set of entities that implement that interface * ex: DomainEvent -> [TransferEvent, ...] * 2. `fields` — mapping a typeName to the polymorphic type it represents * ex: Domain.events -> DomainEvent * * NOTE: in future implementations of ponder, this information could be provided by the schema * using materialized views, and most/all of this code can be removed. */ interface PolymorphicConfig { types: Record<string, PgTable<TableConfig>[]>; fields: Record<string, string>; } interface BuildGraphQLSchemaOptions { schema: Schema; polymorphicConfig?: PolymorphicConfig; metadataProvider: PonderMetadataProvider; } declare function buildGraphQLSchema({ schema: _schema, polymorphicConfig: _polymorphicConfig, metadataProvider, }: BuildGraphQLSchemaOptions): GraphQLSchema; declare function buildDataLoaderCache({ drizzle }: { drizzle: Drizzle<Schema>; }): ({ table }: { table: TableRelationalConfig; }) => DataLoader<string, any, string>; export { type Drizzle, type OnchainTable, type PolymorphicConfig, type Schema, buildDataLoaderCache, buildGraphQLSchema, onchain };