UNPKG

@arkiv-network/sdk

Version:

TypeScript client library for Arkiv's blockchains interactions

67 lines (64 loc) • 2.54 kB
import { isSchema, type Schema, SchemaDefinitionError } from "../schema" import { QueryBuilderBase } from "./builderBase" import { runQuery } from "./engine" /** * Builds and runs a count: how many entities a query matches, without fetching any of them. * * It filters exactly as `client.select()` does — {@link from}, `where`, `ownedBy` and `createdBy` * are the same methods, from the same base — but has nothing to select and no pages, so * {@link fetch} resolves to a `bigint`. Create one with `client.count()`. * * To show the total next to a page of rows, use `select(...).withCount()` instead, which counts in * the same request. * * @typeParam TSchema - The schema named with {@link from}, if any. * * @example * const total = await client.count().from(Posts).ownedBy(account.address).fetch() */ export class CountQueryBuilder< TSchema extends Schema | undefined = undefined, > extends QueryBuilderBase<TSchema> { /** * Counts through a schema: `where` is checked against its indexed columns, and a named schema * counts only entities tagged with its name — so it needs no other filter. * * Returns a new builder, carrying whatever this one already holds; this one is left as it was. * * @throws {SchemaDefinitionError} If `schema` was not built with `defineSchema`. * * @example * client.count().from(Posts) // every post */ from<S extends Schema>(schema: S): CountQueryBuilder<S> { if (!isSchema(schema)) { throw new SchemaDefinitionError("from() takes a schema built with defineSchema(...)") } const typed = this.copy<CountQueryBuilder<S>>() typed._schema = schema return typed } /** * Runs the count. * * Counts every entity the filters match at the block, whether or not it fits the schema — what * `select().from(schema)` leaves out of its pages is still counted. * * @throws {InvalidPredicateError} If no filter has been added, or a filter does not fit the * schema. * @throws {QueryError} If the node rejects the query. * @throws If the node returns no count — it predates the count projection. */ async fetch(): Promise<bigint> { // Nothing but the count is selected, so the node returns no rows. const response = await runQuery(this._client, { query: this.toString(), select: {}, count: true, }) if (response.count === undefined) { throw new Error("The node returned no count. It may predate the count projection.") } return response.count } }