Skip to content

Commit 4f194ca

Browse files
authored
Merge pull request #1 from tjenkinson/smaller-cursor
Restructure cursor to make it smaller
2 parents 2ba7b30 + e16063b commit 4f194ca

File tree

9 files changed

+271
-586
lines changed

9 files changed

+271
-586
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ E.g.
117117
{
118118
"edges": [
119119
{
120-
"cursor": "SuWlzjWxdtSVDzgPp_mVdQH7S4pbbIpNqmJJFWwXOws.9732ntsWW_36ePfEiU1_85i4VHGpnlt60LcekRaV6hZiIfLaDEJyTxv4_mT0gVYjC05he25PbktssRXIQMdfnwfl2PkS47CW75s-XwbfYuhuaZJZfUpZLW5O7xVWf5R2YD7FEdd53lDlXJDbEE5TvRvM8TNkhCSh8LTnJEFNqADHkbWz-H7pDPOaOBsLE3n_EUYcf498pgjPJCRN",
120+
"cursor": "l1X624m67Z5aYShVOLrThEcP7c-ezmCc4C48Dvxtt98.x7zYjxX9VEWDA1KAnJii8zyw5DP_OdIRnSkXATGhwTy6Wf0SSkjdjq6pTl9qxhp87EI-85pUJW9Thz_A6F_8BzlgccgDV-hXWjEj3CsGl96tSaA-X0_qNWBu425Mt6t5j3wNSdk8sSArBQ",
121121
"node": {
122122
"id": 1,
123123
"first_name": "Joe",

src/__snapshots__/sql-cursor-pagination.test.ts.snap

Lines changed: 248 additions & 560 deletions
Large diffs are not rendered by default.

src/arrays.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

src/cursor.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { MaybePromise } from './maybe-promise';
66
import { Cursor } from './zod-models/cursor';
77
import { FieldValue } from './zod-models/field-value';
88
import { FieldWithOrder } from './zod-models/field-with-order';
9-
import { FieldWithValue } from './zod-models/field-with-value';
109

1110
const ivCipherTextRegex = /^([^.]+)\.([^.]+)$/;
1211

@@ -149,14 +148,14 @@ export function buildCursor<TNode extends Record<string, unknown>>({
149148
node: TNode;
150149
sortFields: readonly FieldWithOrder[];
151150
}): Cursor {
152-
const fields: FieldWithValue[] = [];
151+
const fields: Cursor['fields'] = {};
153152

154153
for (const { field } of sortFields) {
155154
const { alias } = parseFieldName(field);
156155
if (!(alias in node)) {
157156
throw new ErrUnexpected(`"${alias}" field is missing`);
158157
}
159-
fields.push({ field: alias, value: FieldValue.parse(node[alias]) });
158+
fields[alias] = FieldValue.parse(node[alias]);
160159
}
161160

162161
return { fields, queryName };

src/set.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function areSetsEqual<T>(a: ReadonlySet<T>, b: ReadonlySet<T>): boolean {
2+
if (a.size !== b.size) return false;
3+
for (const _a of a) if (!b.has(_a)) return false;
4+
return true;
5+
}

src/sql-cursor-pagination.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,11 @@ describe('SqlCursorPagination', () => {
623623
query: {
624624
beforeCursor: all.edges[0].cursor,
625625
last: 1,
626-
sortFields: [{ field: 'email', order: Asc }],
626+
sortFields: [
627+
{ field: 'email', order: Asc },
628+
{ field: 'last_name', order: Asc },
629+
{ field: 'id', order: Asc },
630+
],
627631
},
628632
}),
629633
).rejects.toThrowError(ErrBeforeCursorWrongSortConfig);

src/sql-cursor-pagination.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import pMap from 'p-map';
2-
import { areArraysEqual } from './arrays';
32
import { notNull } from './assert';
43
import { RawCursor, buildCursor, encryptCursor, resolveCursor } from './cursor';
54
import { CursorSecret } from './cursor-secret';
@@ -22,6 +21,7 @@ import {
2221
import { parseFieldName } from './field-name';
2322
import { MaybePromise } from './maybe-promise';
2423
import { FragmentBuilder, QueryBuilder } from './query-builder';
24+
import { areSetsEqual } from './set';
2525
import { Cursor } from './zod-models/cursor';
2626
import { FieldWithOrder } from './zod-models/field-with-order';
2727
import { GenericQueryResult } from './zod-models/generic-query-result';
@@ -309,9 +309,9 @@ export async function withPagination<
309309

310310
// fields in the cursor must match the ones being requested
311311
if (
312-
!areArraysEqual(
313-
sortFields.map(({ field }) => parseFieldName(field).name),
314-
cursor.fields.map(({ field }) => field),
312+
!areSetsEqual(
313+
new Set(sortFields.map(({ field }) => parseFieldName(field).name)),
314+
new Set(Object.keys(cursor.fields)),
315315
)
316316
) {
317317
if (type === 'before') {
@@ -331,7 +331,8 @@ export async function withPagination<
331331
whereQuery.appendText(`(`);
332332
for (let j = 0; j <= i; j++) {
333333
const { field, order } = sortFields[j];
334-
const { value } = c.fields[j];
334+
const fieldName = parseFieldName(field).name;
335+
const value = c.fields[fieldName];
335336
const sign =
336337
i === j
337338
? maybeFlip(order, type === 'before') === Asc
@@ -341,7 +342,7 @@ export async function withPagination<
341342

342343
if (j > 0) whereQuery.appendText(` AND `);
343344
whereQuery
344-
.appendText(`${quoteField(parseFieldName(field).name)}${sign}`)
345+
.appendText(`${quoteField(fieldName)}${sign}`)
345346
.appendValue(value);
346347
}
347348
whereQuery.appendText(`)`);

src/zod-models/cursor.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { z } from 'zod';
2-
import { FieldWithValue } from './field-with-value';
2+
import { FieldName } from './field-name';
3+
import { FieldValue } from './field-value';
34
import { QueryName } from './query-name';
45

56
export const Cursor = z
67
.object({
7-
fields: z.array(FieldWithValue).min(1),
8+
fields: z.record(FieldName, FieldValue),
89
queryName: QueryName,
910
})
1011
.strict()

src/zod-models/field-with-value.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)