UNPKG

convex

Version:

Client for the Convex Cloud

195 lines (194 loc) 5.13 kB
"use strict"; import { jsonToConvex } from "../../values/index.js"; import { performAsyncSyscall, performSyscall } from "./syscall.js"; import { filterBuilderImpl, serializeExpression } from "./filter_builder_impl.js"; import { IndexRangeBuilderImpl } from "./index_range_builder_impl.js"; export class QueryInitializerImpl { constructor(tableName) { this.tableName = tableName; } withIndex(indexName, indexRange) { const rangeBuilder = indexRange(IndexRangeBuilderImpl.new()); return new QueryImpl({ source: { type: "IndexRange", indexName: this.tableName + "." + indexName, range: rangeBuilder.export(), order: "asc" }, operators: [] }); } fullTableScan() { return new QueryImpl({ source: { type: "FullTableScan", tableName: this.tableName, order: "asc" }, operators: [] }); } order(order) { return this.fullTableScan().order(order); } async count() { const syscallJSON = await performAsyncSyscall("count", { table: this.tableName }); const syscallResult = jsonToConvex(syscallJSON); return syscallResult; } filter(predicate) { return this.fullTableScan().filter(predicate); } limit(n) { return this.fullTableScan().limit(n); } collect() { return this.fullTableScan().collect(); } take(n) { return this.fullTableScan().take(n); } paginate(options) { return this.fullTableScan().paginate(options); } first() { return this.fullTableScan().first(); } unique() { return this.fullTableScan().unique(); } [Symbol.asyncIterator]() { return this.fullTableScan()[Symbol.asyncIterator](); } } function throwClosedError(type) { throw new Error( type === "consumed" ? "This query is closed and can't emit any more values." : "This query has been chained with another operator and can't be reused." ); } class QueryImpl { constructor(query) { this.state = { type: "preparing", query }; } takeQuery() { if (this.state.type !== "preparing") { throw new Error( "A query can only be chained once and can't be chained after iteration begins." ); } const query = this.state.query; this.state = { type: "closed" }; return query; } startQuery() { if (this.state.type === "executing") { throw new Error("Iteration can only begin on a query once."); } if (this.state.type === "closed" || this.state.type === "consumed") { throwClosedError(this.state.type); } const query = this.state.query; const { queryId } = performSyscall("queryStream", { query }); this.state = { type: "executing", queryId }; return queryId; } closeQuery() { if (this.state.type === "executing") { const queryId = this.state.queryId; performSyscall("queryCleanup", { queryId }); } this.state = { type: "consumed" }; } order(order) { const query = this.takeQuery(); query.source.order = order; return new QueryImpl(query); } filter(predicate) { const query = this.takeQuery(); query.operators.push({ filter: serializeExpression(predicate(filterBuilderImpl)) }); return new QueryImpl(query); } limit(n) { const query = this.takeQuery(); query.operators.push({ limit: n }); return new QueryImpl(query); } [Symbol.asyncIterator]() { this.startQuery(); return this; } async next() { if (this.state.type === "closed" || this.state.type === "consumed") { throwClosedError(this.state.type); } const queryId = this.state.type === "preparing" ? this.startQuery() : this.state.queryId; const { value, done } = await performAsyncSyscall("queryStreamNext", { queryId }); if (done) { this.closeQuery(); } const convexValue = jsonToConvex(value); return { value: convexValue, done }; } return() { this.closeQuery(); return Promise.resolve({ done: true, value: void 0 }); } async paginate(options) { const query = this.takeQuery(); const pageSize = options.numItems; const cursor = options.cursor; const maximumRowsRead = options.maximumRowsRead ?? null; const { page, isDone, continueCursor } = await performAsyncSyscall( "queryPage", { query, cursor, pageSize, maximumRowsRead } ); return { page: page.map(jsonToConvex), isDone, continueCursor }; } async collect() { const out = []; for await (const item of this) { out.push(item); } return out; } async take(n) { return this.limit(n).collect(); } async first() { const first_array = await this.take(1); return first_array.length === 0 ? null : first_array[0]; } async unique() { const first_two_array = await this.take(2); if (first_two_array.length === 0) { return null; } if (first_two_array.length === 2) { throw new Error("unique() query returned more than one result"); } return first_two_array[0]; } } //# sourceMappingURL=query_impl.js.map