convex-helpers
Version:
A collection of useful code to complement the official convex package.
116 lines • 5.42 kB
TypeScript
import type { Value } from "convex/values";
import type { DataModelFromSchemaDefinition, DocumentByName, GenericDataModel, GenericDatabaseReader, IndexNames, NamedTableInfo, SchemaDefinition, TableNamesInDataModel } from "convex/server";
import { StreamDatabaseReader } from "./stream.js";
export type IndexKey = (Value | undefined)[];
export type PageRequest<DataModel extends GenericDataModel, T extends TableNamesInDataModel<DataModel>> = {
/** Request a page of documents from this table. */
table: T;
/** Where the page starts. Default or empty array is the start of the table. */
startIndexKey?: IndexKey;
/** Whether the startIndexKey is inclusive. Default is false. */
startInclusive?: boolean;
/** Where the page ends. If provided, all documents up to this key will be
* included, if possible. targetMaxRows will be ignored (but absoluteMaxRows
* will not). This ensures adjacent pages stay adjacent, even as they grow.
* An empty array means the end of the table.
*/
endIndexKey?: IndexKey;
/** Whether the endIndexKey is inclusive. Default is true.*/
endInclusive?: boolean;
/** Maximum number of rows to return, as long as endIndexKey is not provided.
* Default is 100.
*/
targetMaxRows?: number;
/** Absolute maximum number of rows to return, even if endIndexKey is
* provided. Use this to prevent a single page from growing too large, but
* watch out because gaps can form between pages.
* Default is unlimited.
*/
absoluteMaxRows?: number;
/** Whether the index is walked in ascending or descending order. Default is
* ascending.
*/
order?: "asc" | "desc";
/** Which index to walk.
* Default is by_creation_time.
*/
index?: IndexNames<NamedTableInfo<DataModel, T>>;
/** If index is not by_creation_time or by_id,
* you need to provide the index fields, either directly or from the schema.
* schema can be found with
* `import schema from "./schema";`
*/
schema?: SchemaDefinition<any, boolean>;
/** The fields of the index, if you specified an index and not a schema. */
indexFields?: string[];
};
export type PageResponse<DataModel extends GenericDataModel, T extends TableNamesInDataModel<DataModel>> = {
/** Page of documents in the table.
* Order is by the `index`, possibly reversed by `order`.
*/
page: DocumentByName<DataModel, T>[];
/** hasMore is true if this page did not exhaust the queried range.*/
hasMore: boolean;
/** indexKeys[i] is the index key for the document page[i].
* indexKeys can be used as `startIndexKey` or `endIndexKey` to fetch pages
* relative to this one.
*/
indexKeys: IndexKey[];
};
/**
* Get a single page of documents from a table.
* See examples in README.
* @param ctx A ctx from a query or mutation context.
* @param request What page to get.
* @returns { page, hasMore, indexKeys }.
*/
export declare function getPage<DataModel extends GenericDataModel, T extends TableNamesInDataModel<DataModel>>(ctx: {
db: GenericDatabaseReader<DataModel>;
}, request: PageRequest<DataModel, T>): Promise<PageResponse<DataModel, T>>;
export declare function streamQuery<DataModel extends GenericDataModel, T extends TableNamesInDataModel<DataModel>>(ctx: {
db: GenericDatabaseReader<DataModel>;
}, request: Omit<PageRequest<DataModel, T>, "targetMaxRows" | "absoluteMaxRows">): AsyncGenerator<[DocumentByName<DataModel, T>, IndexKey]>;
/**
* Simpified version of `getPage` that you can use for one-off queries that
* don't need to be reactive.
*
* These two queries are roughly equivalent:
*
* ```ts
* await db.query(table)
* .withIndex(index, q=>q.eq(field, value))
* .order("desc")
* .paginate(opts)
*
* await paginator(db, schema)
* .query(table)
* .withIndex(index, q=>q.eq(field, value))
* .order("desc")
* .paginate(opts)
* ```
*
* Differences:
*
* - `paginator` does not automatically track the end of the page for when
* the query reruns. The standard `paginate` call will record the end of the page,
* so a client can have seamless reactive pagination. To pin the end of the page,
* you can use the `endCursor` option. This does not happen automatically.
* Read more [here](https://stack.convex.dev/pagination#stitching-the-pages-together)
* - `paginator` can be called multiple times in a query or mutation,
* and within Convex components.
* - Cursors are not encrypted.
* - `.filter()` and the `filter()` convex-helper are not supported.
* Filter the returned `page` in TypeScript instead.
* - System tables like _storage and _scheduled_functions are not supported.
* - Having a schema is required.
*
* @argument opts.cursor Where to start the page. This should come from
* `continueCursor` in the previous page.
* @argument opts.endCursor Where to end the page. This should from from
* `continueCursor` in the *current* page.
* If not provided, the page will end when it reaches `options.opts.numItems`.
* @argument options.schema If you use an index that is not by_creation_time
* or by_id, you need to provide the schema.
*/
export declare function paginator<Schema extends SchemaDefinition<any, boolean>>(db: GenericDatabaseReader<DataModelFromSchemaDefinition<Schema>>, schema: Schema): StreamDatabaseReader<Schema>;
//# sourceMappingURL=pagination.d.ts.map