11/* eslint-disable no-unexpected-multiline */
22import type { Value } from "convex/values" ;
3- import { convexToJson , jsonToConvex } from "convex/values" ;
3+ import { convexToJson , compareValues , jsonToConvex } from "convex/values" ;
44import type {
55 DataModelFromSchemaDefinition ,
66 DocumentByInfo ,
@@ -21,9 +21,8 @@ import type {
2121 SystemDataModel ,
2222 TableNamesInDataModel ,
2323} from "convex/server" ;
24- import { compareValues } from "./compare.js" ;
2524
26- export type IndexKey = Value [ ] ;
25+ export type IndexKey = ( Value | undefined ) [ ] ;
2726
2827//
2928// Helper functions
@@ -349,7 +348,7 @@ abstract class QueryStream<T extends GenericStreamItem>
349348 } ;
350349 if ( opts . cursor !== null ) {
351350 newStartKey = {
352- key : jsonToConvex ( JSON . parse ( opts . cursor ) ) as IndexKey ,
351+ key : deserializeCursor ( opts . cursor ) ,
353352 inclusive : false ,
354353 } ;
355354 }
@@ -362,7 +361,7 @@ abstract class QueryStream<T extends GenericStreamItem>
362361 let maxRows : number | undefined = opts . numItems ;
363362 if ( opts . endCursor ) {
364363 newEndKey = {
365- key : jsonToConvex ( JSON . parse ( opts . endCursor ) ) as IndexKey ,
364+ key : deserializeCursor ( opts . endCursor ) ,
366365 inclusive : true ,
367366 } ;
368367 // If there's an endCursor, continue until we get there even if it's more
@@ -391,7 +390,7 @@ abstract class QueryStream<T extends GenericStreamItem>
391390 ( maxRowsToRead !== undefined && indexKeys . length >= maxRowsToRead )
392391 ) {
393392 hasMore = true ;
394- continueCursor = JSON . stringify ( convexToJson ( indexKey as Value ) ) ;
393+ continueCursor = serializeCursor ( indexKey ) ;
395394 break ;
396395 }
397396 }
@@ -410,9 +409,7 @@ abstract class QueryStream<T extends GenericStreamItem>
410409 isDone : ! hasMore ,
411410 continueCursor,
412411 pageStatus,
413- splitCursor : splitCursor
414- ? JSON . stringify ( convexToJson ( splitCursor as Value ) )
415- : undefined ,
412+ splitCursor : splitCursor ? serializeCursor ( splitCursor ) : undefined ,
416413 } ;
417414 }
418415 async collect ( ) {
@@ -1851,3 +1848,26 @@ function compareKeys(key1: Key, key2: Key): number {
18511848 // of key2.kind is valid...
18521849 throw new Error ( `Unexpected key kind: ${ key1 . kind as any } ` ) ;
18531850}
1851+
1852+ function serializeCursor ( key : IndexKey ) : string {
1853+ return JSON . stringify (
1854+ convexToJson (
1855+ key . map ( ( v ) : Value => ( v === undefined ? { $undefined : true } : v ) ) ,
1856+ ) ,
1857+ ) ;
1858+ }
1859+
1860+ function deserializeCursor ( cursor : string ) : IndexKey {
1861+ return ( jsonToConvex ( JSON . parse ( cursor ) ) as Value [ ] ) . map ( ( v ) => {
1862+ if ( typeof v === "object" && ! Array . isArray ( v ) && v !== null ) {
1863+ const entries = Object . entries ( v ) ;
1864+ if ( entries . length === 1 && entries [ 0 ] ! [ 0 ] === "$undefined" ) {
1865+ // This is a special case for the undefined value.
1866+ // It's not a valid value in the index, but it's a valid value in the
1867+ // cursor.
1868+ return undefined ;
1869+ }
1870+ }
1871+ return v ;
1872+ } ) ;
1873+ }
0 commit comments