@proteinjs/db-ui 1.8.5 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/generated/index.js +1 -1
- package/dist/generated/index.js.map +1 -1
- package/dist/src/table/QueryCursorLoader.d.ts +10 -14
- package/dist/src/table/QueryCursorLoader.d.ts.map +1 -1
- package/dist/src/table/QueryCursorLoader.js +20 -41
- package/dist/src/table/QueryCursorLoader.js.map +1 -1
- package/dist/test/QueryCursorLoader.test.d.ts +1 -1
- package/dist/test/QueryCursorLoader.test.d.ts.map +1 -1
- package/dist/test/QueryCursorLoader.test.js +122 -95
- package/dist/test/QueryCursorLoader.test.js.map +1 -1
- package/generated/index.ts +1 -1
- package/package.json +3 -3
- package/src/table/QueryCursorLoader.ts +23 -43
- package/test/QueryCursorLoader.test.ts +87 -94
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,25 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.9.1](https://github.com/proteinjs/db/compare/@proteinjs/db-ui@1.9.0...@proteinjs/db-ui@1.9.1) (2026-08-14)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @proteinjs/db-ui
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# [1.9.0](https://github.com/proteinjs/db/compare/@proteinjs/db-ui@1.8.5...@proteinjs/db-ui@1.9.0) (2026-08-14)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
* cursor-window paging owner; RecordIterator migrated off offset paging ([453c4a2](https://github.com/proteinjs/db/commit/453c4a2a5f87bd7b58b0042185100bcf9ae0e183))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
6
25
|
## [1.8.5](https://github.com/proteinjs/db/compare/@proteinjs/db-ui@1.8.4...@proteinjs/db-ui@1.8.5) (2026-08-14)
|
|
7
26
|
|
|
8
27
|
|
package/dist/generated/index.js
CHANGED
|
@@ -28,7 +28,7 @@ require("react");
|
|
|
28
28
|
require("string");
|
|
29
29
|
require("uuid");
|
|
30
30
|
/** Generate Source Graph */
|
|
31
|
-
var sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"@proteinjs/db-ui/QueryCursorLoader\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"QueryCursorLoader\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/table/QueryCursorLoader.ts\",\"qualifiedName\":\"@proteinjs/db-ui/QueryCursorLoader\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"reactQueryKeys\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"ReactQueryKeys\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/ReactQueryKeys\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"sort\",\"type\":{\"packageName\":\"\",\"name\":\"SortCriteria<T>[]\",\"filePath\":null,\"qualifiedName\":\"/SortCriteria<T>[]\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<T>\",\"filePath\":null,\"qualifiedName\":\"/Table<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"createQuery\",\"type\":{\"packageName\":\"\",\"name\":\"() => QueryBuilder<T>\",\"filePath\":null,\"qualifiedName\":\"/() => QueryBuilder<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"queryOptions\",\"type\":{\"packageName\":\"\",\"name\":\"QueryOptions<T>\",\"filePath\":null,\"qualifiedName\":\"/QueryOptions<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"}],\"methods\":[{\"name\":\"loadWindow\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<CursorWindow<T>>\",\"filePath\":null,\"qualifiedName\":\"/Promise<CursorWindow<T>>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"cursor\",\"type\":{\"packageName\":\"\",\"name\":\"CursorValue | null\",\"filePath\":null,\"qualifiedName\":\"/CursorValue | null\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"windowSize\",\"type\":{\"packageName\":\"\",\"name\":\"number\",\"filePath\":null,\"qualifiedName\":\"/number\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"buildWindowQuery\",\"returnType\":{\"packageName\":\"\",\"name\":\"QueryBuilder<T>\",\"filePath\":null,\"qualifiedName\":\"/QueryBuilder<T>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[{\"name\":\"cursor\",\"type\":{\"packageName\":\"\",\"name\":\"CursorValue | null\",\"filePath\":null,\"qualifiedName\":\"/CursorValue | null\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"windowSize\",\"type\":{\"packageName\":\"\",\"name\":\"number\",\"filePath\":null,\"qualifiedName\":\"/number\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"deriveNextCursor\",\"returnType\":{\"packageName\":\"\",\"name\":\"CursorValue | null\",\"filePath\":null,\"qualifiedName\":\"/CursorValue | null\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[{\"name\":\"rows\",\"type\":{\"packageName\":\"\",\"name\":\"T[]\",\"filePath\":null,\"qualifiedName\":\"/T[]\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"windowSize\",\"type\":{\"packageName\":\"\",\"name\":\"number\",\"filePath\":null,\"qualifiedName\":\"/number\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[\"/T extends Record\"],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"CursorLoader\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/CursorLoader\",\"properties\":[],\"methods\":[],\"typeParameters\":[\"/T\"],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/ui/CursorLoader\"},{\"v\":\"@proteinjs/db-ui/QueryTableLoader\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"QueryTableLoader\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/table/QueryTableLoader.ts\",\"qualifiedName\":\"@proteinjs/db-ui/QueryTableLoader\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"rowCountQb\",\"type\":{\"packageName\":\"\",\"name\":\"QueryBuilder<T>\",\"filePath\":null,\"qualifiedName\":\"/QueryBuilder<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"paginationQb\",\"type\":{\"packageName\":\"\",\"name\":\"QueryBuilder<T>\",\"filePath\":null,\"qualifiedName\":\"/QueryBuilder<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"reactQueryKeys\",\"type\":{\"packageName\":\"\",\"name\":\"TableLoader<T>['reactQueryKeys']\",\"filePath\":null,\"qualifiedName\":\"/TableLoader<T>['reactQueryKeys']\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<T>\",\"filePath\":null,\"qualifiedName\":\"/Table<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"query\",\"type\":{\"packageName\":\"\",\"name\":\"Query<T>\",\"filePath\":null,\"qualifiedName\":\"/Query<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"sort\",\"type\":{\"packageName\":\"\",\"name\":\"SortCriteria<T>[]\",\"filePath\":null,\"qualifiedName\":\"/SortCriteria<T>[]\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"queryOptions\",\"type\":{\"packageName\":\"\",\"name\":\"QueryOptions<T>\",\"filePath\":null,\"qualifiedName\":\"/QueryOptions<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"}],\"methods\":[{\"name\":\"load\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<RowWindow<T>>\",\"filePath\":null,\"qualifiedName\":\"/Promise<RowWindow<T>>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"startIndex\",\"type\":{\"packageName\":\"\",\"name\":\"number\",\"filePath\":null,\"qualifiedName\":\"/number\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"endIndex\",\"type\":{\"packageName\":\"\",\"name\":\"number\",\"filePath\":null,\"qualifiedName\":\"/number\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"skipRowCount\",\"type\":{\"packageName\":\"\",\"name\":\"boolean\",\"filePath\":null,\"qualifiedName\":\"/boolean\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[\"/T extends Record\"],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"TableLoader\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/TableLoader\",\"properties\":[],\"methods\":[],\"typeParameters\":[\"/T\"],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/ui/TableLoader\"},{\"v\":\"@proteinjs/db-ui/RecordFormCustomization\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"RecordFormCustomization\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/form/RecordFormCustomization.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/RecordFormCustomization\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<any>\",\"filePath\":null,\"qualifiedName\":\"/Table<any>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"getFormButtons\",\"returnType\":{\"packageName\":\"\",\"name\":\"FormButtons<any>\",\"filePath\":null,\"qualifiedName\":\"/FormButtons<any>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"record\",\"type\":{\"packageName\":\"\",\"name\":\"any\",\"filePath\":null,\"qualifiedName\":\"/any\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"defaultFormButtons\",\"type\":{\"packageName\":\"\",\"name\":\"FormButtons<any>\",\"filePath\":null,\"qualifiedName\":\"/FormButtons<any>\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getFieldLayout\",\"returnType\":{\"packageName\":\"\",\"name\":\"string[] | string[][]\",\"filePath\":null,\"qualifiedName\":\"/string[] | string[][]\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"record\",\"type\":{\"packageName\":\"\",\"name\":\"any\",\"filePath\":null,\"qualifiedName\":\"/any\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"defaultFieldLayout\",\"type\":{\"packageName\":\"\",\"name\":\"string[] | string[][]\",\"filePath\":null,\"qualifiedName\":\"/string[] | string[][]\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/reflection\",\"name\":\"Loadable\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/reflection/Loadable\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/reflection/Loadable\"},{\"v\":\"@proteinjs/db-ui/hashGeneratorPage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"hashGeneratorPage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/HashGeneratorPage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/hashGeneratorPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/ui/Page\"},{\"v\":\"@proteinjs/db-ui/recordFormPage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"recordFormPage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/RecordFormPage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/recordFormPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/db-ui/recordTablePage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"recordTablePage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/RecordTablePage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/recordTablePage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/db-ui/tablesPage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"tablesPage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/TablesPage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/tablesPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/db-ui/uuidGeneratorPage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"uuidGeneratorPage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/UuidGeneratorPage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/uuidGeneratorPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/db-ui/SpecificTableProps\"},{\"v\":\"@proteinjs/db-ui/MigrationRecordFormCustomization\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"MigrationRecordFormCustomization\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/form/customizations/MigrationRecordFormCustomization.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/MigrationRecordFormCustomization\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"table\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"getFormButtons\",\"returnType\":{\"packageName\":\"\",\"name\":\"FormButtons<any>\",\"filePath\":null,\"qualifiedName\":\"/FormButtons<any>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"migration\",\"type\":{\"packageName\":\"@proteinjs/db\",\"name\":\"Migration\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db/Migration\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"defaultFormButtons\",\"type\":{\"packageName\":\"\",\"name\":\"FormButtons<any>\",\"filePath\":null,\"qualifiedName\":\"/FormButtons<any>\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"RecordFormCustomization\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db-ui/RecordFormCustomization\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[]}],\"sourceType\":2}}],\"edges\":[{\"v\":\"@proteinjs/db-ui/QueryCursorLoader\",\"w\":\"@proteinjs/ui/CursorLoader\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/db-ui/QueryTableLoader\",\"w\":\"@proteinjs/ui/TableLoader\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/db-ui/RecordFormCustomization\",\"w\":\"@proteinjs/reflection/Loadable\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/db-ui/hashGeneratorPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/recordFormPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/recordTablePage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/tablesPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/uuidGeneratorPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/MigrationRecordFormCustomization\",\"w\":\"@proteinjs/db-ui/RecordFormCustomization\",\"value\":\"extends class\"}]}";
|
|
31
|
+
var sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"@proteinjs/db-ui/QueryCursorLoader\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"QueryCursorLoader\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/table/QueryCursorLoader.ts\",\"qualifiedName\":\"@proteinjs/db-ui/QueryCursorLoader\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"reactQueryKeys\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"ReactQueryKeys\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/ReactQueryKeys\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"pager\",\"type\":{\"packageName\":\"\",\"name\":\"CursorWindowPager<T>\",\"filePath\":null,\"qualifiedName\":\"/CursorWindowPager<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"}],\"methods\":[{\"name\":\"loadWindow\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<CursorWindow<T>>\",\"filePath\":null,\"qualifiedName\":\"/Promise<CursorWindow<T>>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"cursor\",\"type\":{\"packageName\":\"\",\"name\":\"CursorValue | null\",\"filePath\":null,\"qualifiedName\":\"/CursorValue | null\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"windowSize\",\"type\":{\"packageName\":\"\",\"name\":\"number\",\"filePath\":null,\"qualifiedName\":\"/number\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[\"/T extends Record\"],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"CursorLoader\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/CursorLoader\",\"properties\":[],\"methods\":[],\"typeParameters\":[\"/T\"],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/ui/CursorLoader\"},{\"v\":\"@proteinjs/db-ui/QueryTableLoader\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"QueryTableLoader\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/table/QueryTableLoader.ts\",\"qualifiedName\":\"@proteinjs/db-ui/QueryTableLoader\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"rowCountQb\",\"type\":{\"packageName\":\"\",\"name\":\"QueryBuilder<T>\",\"filePath\":null,\"qualifiedName\":\"/QueryBuilder<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"paginationQb\",\"type\":{\"packageName\":\"\",\"name\":\"QueryBuilder<T>\",\"filePath\":null,\"qualifiedName\":\"/QueryBuilder<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"reactQueryKeys\",\"type\":{\"packageName\":\"\",\"name\":\"TableLoader<T>['reactQueryKeys']\",\"filePath\":null,\"qualifiedName\":\"/TableLoader<T>['reactQueryKeys']\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<T>\",\"filePath\":null,\"qualifiedName\":\"/Table<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"query\",\"type\":{\"packageName\":\"\",\"name\":\"Query<T>\",\"filePath\":null,\"qualifiedName\":\"/Query<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"sort\",\"type\":{\"packageName\":\"\",\"name\":\"SortCriteria<T>[]\",\"filePath\":null,\"qualifiedName\":\"/SortCriteria<T>[]\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"queryOptions\",\"type\":{\"packageName\":\"\",\"name\":\"QueryOptions<T>\",\"filePath\":null,\"qualifiedName\":\"/QueryOptions<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"}],\"methods\":[{\"name\":\"load\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<RowWindow<T>>\",\"filePath\":null,\"qualifiedName\":\"/Promise<RowWindow<T>>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"startIndex\",\"type\":{\"packageName\":\"\",\"name\":\"number\",\"filePath\":null,\"qualifiedName\":\"/number\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"endIndex\",\"type\":{\"packageName\":\"\",\"name\":\"number\",\"filePath\":null,\"qualifiedName\":\"/number\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"skipRowCount\",\"type\":{\"packageName\":\"\",\"name\":\"boolean\",\"filePath\":null,\"qualifiedName\":\"/boolean\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[\"/T extends Record\"],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"TableLoader\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/TableLoader\",\"properties\":[],\"methods\":[],\"typeParameters\":[\"/T\"],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/ui/TableLoader\"},{\"v\":\"@proteinjs/db-ui/RecordFormCustomization\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"RecordFormCustomization\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/form/RecordFormCustomization.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/RecordFormCustomization\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<any>\",\"filePath\":null,\"qualifiedName\":\"/Table<any>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"getFormButtons\",\"returnType\":{\"packageName\":\"\",\"name\":\"FormButtons<any>\",\"filePath\":null,\"qualifiedName\":\"/FormButtons<any>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"record\",\"type\":{\"packageName\":\"\",\"name\":\"any\",\"filePath\":null,\"qualifiedName\":\"/any\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"defaultFormButtons\",\"type\":{\"packageName\":\"\",\"name\":\"FormButtons<any>\",\"filePath\":null,\"qualifiedName\":\"/FormButtons<any>\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getFieldLayout\",\"returnType\":{\"packageName\":\"\",\"name\":\"string[] | string[][]\",\"filePath\":null,\"qualifiedName\":\"/string[] | string[][]\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"record\",\"type\":{\"packageName\":\"\",\"name\":\"any\",\"filePath\":null,\"qualifiedName\":\"/any\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"defaultFieldLayout\",\"type\":{\"packageName\":\"\",\"name\":\"string[] | string[][]\",\"filePath\":null,\"qualifiedName\":\"/string[] | string[][]\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/reflection\",\"name\":\"Loadable\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/reflection/Loadable\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/reflection/Loadable\"},{\"v\":\"@proteinjs/db-ui/hashGeneratorPage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"hashGeneratorPage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/HashGeneratorPage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/hashGeneratorPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/ui/Page\"},{\"v\":\"@proteinjs/db-ui/recordFormPage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"recordFormPage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/RecordFormPage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/recordFormPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/db-ui/recordTablePage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"recordTablePage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/RecordTablePage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/recordTablePage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/db-ui/tablesPage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"tablesPage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/TablesPage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/tablesPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/db-ui/uuidGeneratorPage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"uuidGeneratorPage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/UuidGeneratorPage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/uuidGeneratorPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/db-ui/SpecificTableProps\"},{\"v\":\"@proteinjs/db-ui/MigrationRecordFormCustomization\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"MigrationRecordFormCustomization\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/form/customizations/MigrationRecordFormCustomization.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/MigrationRecordFormCustomization\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"table\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"getFormButtons\",\"returnType\":{\"packageName\":\"\",\"name\":\"FormButtons<any>\",\"filePath\":null,\"qualifiedName\":\"/FormButtons<any>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"migration\",\"type\":{\"packageName\":\"@proteinjs/db\",\"name\":\"Migration\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db/Migration\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"defaultFormButtons\",\"type\":{\"packageName\":\"\",\"name\":\"FormButtons<any>\",\"filePath\":null,\"qualifiedName\":\"/FormButtons<any>\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"RecordFormCustomization\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db-ui/RecordFormCustomization\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[]}],\"sourceType\":2}}],\"edges\":[{\"v\":\"@proteinjs/db-ui/QueryCursorLoader\",\"w\":\"@proteinjs/ui/CursorLoader\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/db-ui/QueryTableLoader\",\"w\":\"@proteinjs/ui/TableLoader\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/db-ui/RecordFormCustomization\",\"w\":\"@proteinjs/reflection/Loadable\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/db-ui/hashGeneratorPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/recordFormPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/recordTablePage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/tablesPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/uuidGeneratorPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/MigrationRecordFormCustomization\",\"w\":\"@proteinjs/db-ui/RecordFormCustomization\",\"value\":\"extends class\"}]}";
|
|
32
32
|
/** Generate Source Links */
|
|
33
33
|
var QueryCursorLoader_1 = require("../src/table/QueryCursorLoader");
|
|
34
34
|
var QueryTableLoader_1 = require("../src/table/QueryTableLoader");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,0BAAwB;AACxB,2BAAyB;AACzB,+BAA6B;AAC7B,yBAAuB;AACvB,yBAAuB;AACvB,iCAA+B;AAC/B,yBAAuB;AACvB,2BAAyB;AACzB,kBAAgB;AAChB,iBAAe;AACf,kBAAgB;AAChB,gBAAc;AAGd,4BAA4B;AAE5B,IAAM,WAAW,GAAG
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,0BAAwB;AACxB,2BAAyB;AACzB,+BAA6B;AAC7B,yBAAuB;AACvB,yBAAuB;AACvB,iCAA+B;AAC/B,yBAAuB;AACvB,2BAAyB;AACzB,kBAAgB;AAChB,iBAAe;AACf,kBAAgB;AAChB,gBAAc;AAGd,4BAA4B;AAE5B,IAAM,WAAW,GAAG,wrbAAwrb,CAAC;AAG7sb,4BAA4B;AAE5B,oEAAmE;AACnE,kEAAiE;AACjE,+EAA8E;AAC9E,oEAAmE;AACnE,8DAA6D;AAC7D,gEAA+D;AAC/D,sDAAqD;AACrD,oEAAmE;AACnE,gHAA+G;AAE/G,IAAM,WAAW,GAAG;IACnB,oCAAoC,EAAE,qCAAiB;IACvD,mCAAmC,EAAE,mCAAgB;IACrD,0CAA0C,EAAE,iDAAuB;IACnE,oCAAoC,EAAE,qCAAiB;IACvD,iCAAiC,EAAE,+BAAc;IACjD,kCAAkC,EAAE,iCAAe;IACnD,6BAA6B,EAAE,uBAAU;IACzC,oCAAoC,EAAE,qCAAiB;IACvD,mDAAmD,EAAE,mEAAgC;CACrF,CAAC;AAGF,kCAAkC;AAElC,oDAAyD;AACzD,6BAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAGjD,2CAAyB"}
|
|
@@ -1,33 +1,29 @@
|
|
|
1
1
|
import { QueryBuilder, QueryOptions, Record, SortCriteria, Table } from '@proteinjs/db';
|
|
2
2
|
import { CursorLoader, CursorValue, CursorWindow, ReactQueryKeys } from '@proteinjs/ui';
|
|
3
3
|
/**
|
|
4
|
-
* `CursorLoader` over the
|
|
5
|
-
*
|
|
6
|
-
* on a fresh build of the base query, so
|
|
7
|
-
* shift the window frame
|
|
8
|
-
*
|
|
4
|
+
* `CursorLoader` over the db-owned cursor-window machinery (`CursorWindowPager`): each window
|
|
5
|
+
* carries a lexicographic continuation past the anchor row — the primary sort axes plus a
|
|
6
|
+
* unique `id` tiebreak — and `paginate(0, windowSize)` on a fresh build of the base query, so
|
|
7
|
+
* rows created or removed while paging can never shift the window frame, and ties on the sort
|
|
8
|
+
* axis can never skip or duplicate boundary rows. Cursors are the pager's anchors encoded as
|
|
9
|
+
* strings (house `Serializer`, so dates/moments survive react-query page params).
|
|
9
10
|
*
|
|
10
11
|
* `dataKey` is the table name — table-level invalidation (`useTableMutation`) reaches every
|
|
11
12
|
* cursor query over it; `dataQueryKey` is the serialized query + sort.
|
|
12
13
|
*/
|
|
13
14
|
export declare class QueryCursorLoader<T extends Record> implements CursorLoader<T> {
|
|
14
|
-
private table;
|
|
15
|
-
private createQuery;
|
|
16
|
-
private queryOptions?;
|
|
17
15
|
reactQueryKeys: ReactQueryKeys;
|
|
18
|
-
private
|
|
16
|
+
private pager;
|
|
19
17
|
/**
|
|
20
18
|
* @param table the table to load windows from
|
|
21
19
|
* @param createQuery factory producing a FRESH conditions-only QueryBuilder per call —
|
|
22
|
-
* builders are mutable, so every window builds its own to hang the cursor
|
|
20
|
+
* builders are mutable, so every window builds its own to hang the cursor conditions,
|
|
23
21
|
* sort, and pagination on
|
|
24
22
|
* @param sort the sort criteria to apply to every window; the primary criterion is the
|
|
25
|
-
* cursor axis
|
|
23
|
+
* cursor axis (the pager appends the `id` tiebreak)
|
|
26
24
|
* @param queryOptions query options passed through to every window query
|
|
27
25
|
*/
|
|
28
|
-
constructor(table: Table<T>, createQuery: () => QueryBuilder<T>, sort?: SortCriteria<T>[], queryOptions?: QueryOptions<T>
|
|
26
|
+
constructor(table: Table<T>, createQuery: () => QueryBuilder<T>, sort?: SortCriteria<T>[], queryOptions?: QueryOptions<T>);
|
|
29
27
|
loadWindow(cursor: CursorValue | null, windowSize: number): Promise<CursorWindow<T>>;
|
|
30
|
-
private buildWindowQuery;
|
|
31
|
-
private deriveNextCursor;
|
|
32
28
|
}
|
|
33
29
|
//# sourceMappingURL=QueryCursorLoader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryCursorLoader.d.ts","sourceRoot":"","sources":["../../../src/table/QueryCursorLoader.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"QueryCursorLoader.d.ts","sourceRoot":"","sources":["../../../src/table/QueryCursorLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3G,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAExF;;;;;;;;;;GAUG;AACH,qBAAa,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAE,YAAW,YAAY,CAAC,CAAC,CAAC;IACzE,cAAc,EAAE,cAAc,CAAC;IAC/B,OAAO,CAAC,KAAK,CAAuB;IAEpC;;;;;;;;OAQG;gBAED,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,WAAW,EAAE,MAAM,YAAY,CAAC,CAAC,CAAC,EAClC,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,EACxB,YAAY,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;IAU1B,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;CAQ3F"}
|
|
@@ -39,11 +39,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
exports.QueryCursorLoader = void 0;
|
|
40
40
|
var db_1 = require("@proteinjs/db");
|
|
41
41
|
/**
|
|
42
|
-
* `CursorLoader` over the
|
|
43
|
-
*
|
|
44
|
-
* on a fresh build of the base query, so
|
|
45
|
-
* shift the window frame
|
|
46
|
-
*
|
|
42
|
+
* `CursorLoader` over the db-owned cursor-window machinery (`CursorWindowPager`): each window
|
|
43
|
+
* carries a lexicographic continuation past the anchor row — the primary sort axes plus a
|
|
44
|
+
* unique `id` tiebreak — and `paginate(0, windowSize)` on a fresh build of the base query, so
|
|
45
|
+
* rows created or removed while paging can never shift the window frame, and ties on the sort
|
|
46
|
+
* axis can never skip or duplicate boundary rows. Cursors are the pager's anchors encoded as
|
|
47
|
+
* strings (house `Serializer`, so dates/moments survive react-query page params).
|
|
47
48
|
*
|
|
48
49
|
* `dataKey` is the table name — table-level invalidation (`useTableMutation`) reaches every
|
|
49
50
|
* cursor query over it; `dataQueryKey` is the serialized query + sort.
|
|
@@ -52,60 +53,38 @@ var QueryCursorLoader = /** @class */ (function () {
|
|
|
52
53
|
/**
|
|
53
54
|
* @param table the table to load windows from
|
|
54
55
|
* @param createQuery factory producing a FRESH conditions-only QueryBuilder per call —
|
|
55
|
-
* builders are mutable, so every window builds its own to hang the cursor
|
|
56
|
+
* builders are mutable, so every window builds its own to hang the cursor conditions,
|
|
56
57
|
* sort, and pagination on
|
|
57
58
|
* @param sort the sort criteria to apply to every window; the primary criterion is the
|
|
58
|
-
* cursor axis
|
|
59
|
+
* cursor axis (the pager appends the `id` tiebreak)
|
|
59
60
|
* @param queryOptions query options passed through to every window query
|
|
60
61
|
*/
|
|
61
62
|
function QueryCursorLoader(table, createQuery, sort, queryOptions) {
|
|
62
|
-
|
|
63
|
-
this.
|
|
64
|
-
this.queryOptions = queryOptions;
|
|
65
|
-
this.sort = sort ? sort : [{ field: 'created', desc: true }];
|
|
63
|
+
var effectiveSort = sort ? sort : [{ field: 'created', desc: true }];
|
|
64
|
+
this.pager = new db_1.CursorWindowPager(table, createQuery, effectiveSort, { queryOptions: queryOptions });
|
|
66
65
|
this.reactQueryKeys = {
|
|
67
|
-
dataKey:
|
|
68
|
-
dataQueryKey: JSON.stringify({ query:
|
|
66
|
+
dataKey: table.name,
|
|
67
|
+
dataQueryKey: JSON.stringify({ query: createQuery(), sort: effectiveSort }),
|
|
69
68
|
};
|
|
70
69
|
}
|
|
71
70
|
QueryCursorLoader.prototype.loadWindow = function (cursor, windowSize) {
|
|
72
71
|
return __awaiter(this, void 0, void 0, function () {
|
|
73
|
-
var
|
|
72
|
+
var anchor, window;
|
|
74
73
|
return __generator(this, function (_a) {
|
|
75
74
|
switch (_a.label) {
|
|
76
75
|
case 0:
|
|
77
|
-
|
|
78
|
-
return [4 /*yield*/,
|
|
76
|
+
anchor = cursor === null ? null : db_1.CursorWindowPager.decodeAnchor(cursor);
|
|
77
|
+
return [4 /*yield*/, this.pager.loadWindow(anchor, windowSize)];
|
|
79
78
|
case 1:
|
|
80
|
-
|
|
81
|
-
return [2 /*return*/, {
|
|
79
|
+
window = _a.sent();
|
|
80
|
+
return [2 /*return*/, {
|
|
81
|
+
rows: window.rows,
|
|
82
|
+
nextCursor: window.nextAnchor ? db_1.CursorWindowPager.encodeAnchor(window.nextAnchor) : null,
|
|
83
|
+
}];
|
|
82
84
|
}
|
|
83
85
|
});
|
|
84
86
|
});
|
|
85
87
|
};
|
|
86
|
-
QueryCursorLoader.prototype.buildWindowQuery = function (cursor, windowSize) {
|
|
87
|
-
var qb = this.createQuery();
|
|
88
|
-
var primarySort = this.sort[0];
|
|
89
|
-
if (cursor !== null) {
|
|
90
|
-
qb.condition({
|
|
91
|
-
field: primarySort.field,
|
|
92
|
-
operator: primarySort.desc ? '<' : '>',
|
|
93
|
-
value: cursor,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
return qb.sort(this.sort).paginate({ start: 0, end: windowSize });
|
|
97
|
-
};
|
|
98
|
-
QueryCursorLoader.prototype.deriveNextCursor = function (rows, windowSize) {
|
|
99
|
-
// A short window means the data set is exhausted; a full one implies more may exist —
|
|
100
|
-
// the next (short or empty) window settles it.
|
|
101
|
-
if (rows.length < windowSize) {
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
// NULL cursor-field rows collect at the tail under the sort, and a null tail can't
|
|
105
|
-
// anchor a cursor: the data set's dated rows are exhausted, so paging stops here.
|
|
106
|
-
var tail = rows[rows.length - 1][this.sort[0].field];
|
|
107
|
-
return tail == null ? null : tail;
|
|
108
|
-
};
|
|
109
88
|
return QueryCursorLoader;
|
|
110
89
|
}());
|
|
111
90
|
exports.QueryCursorLoader = QueryCursorLoader;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryCursorLoader.js","sourceRoot":"","sources":["../../../src/table/QueryCursorLoader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"QueryCursorLoader.js","sourceRoot":"","sources":["../../../src/table/QueryCursorLoader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oCAA2G;AAG3G;;;;;;;;;;GAUG;AACH;IAIE;;;;;;;;OAQG;IACH,2BACE,KAAe,EACf,WAAkC,EAClC,IAAwB,EACxB,YAA8B;QAE9B,IAAM,aAAa,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAoB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,IAAI,CAAC,KAAK,GAAG,IAAI,sBAAiB,CAAI,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE,YAAY,cAAA,EAAE,CAAC,CAAC;QAC3F,IAAI,CAAC,cAAc,GAAG;YACpB,OAAO,EAAE,KAAK,CAAC,IAAI;YACnB,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;SAC5E,CAAC;IACJ,CAAC;IAEK,sCAAU,GAAhB,UAAiB,MAA0B,EAAE,UAAkB;;;;;;wBACvD,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,sBAAiB,CAAC,YAAY,CAAC,MAAgB,CAAC,CAAC;wBAC1E,qBAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,EAAA;;wBAAxD,MAAM,GAAG,SAA+C;wBAC9D,sBAAO;gCACL,IAAI,EAAE,MAAM,CAAC,IAAI;gCACjB,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,sBAAiB,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI;6BACzF,EAAC;;;;KACH;IACH,wBAAC;AAAD,CAAC,AAnCD,IAmCC;AAnCY,8CAAiB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import '../generated/index';
|
|
2
2
|
//# sourceMappingURL=QueryCursorLoader.test.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryCursorLoader.test.d.ts","sourceRoot":"","sources":["../../test/QueryCursorLoader.test.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"QueryCursorLoader.test.d.ts","sourceRoot":"","sources":["../../test/QueryCursorLoader.test.ts"],"names":[],"mappings":"AAcA,OAAO,oBAAoB,CAAC"}
|
|
@@ -1,15 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -51,30 +40,39 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
51
40
|
};
|
|
52
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
42
|
/**
|
|
54
|
-
* QueryCursorLoader (src/table/QueryCursorLoader.ts)
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* the
|
|
43
|
+
* QueryCursorLoader (src/table/QueryCursorLoader.ts) as the thin `CursorLoader` adapter over
|
|
44
|
+
* the db-owned `CursorWindowPager`: react-query key derivation, string-cursor encode/decode
|
|
45
|
+
* threading into the pager's lexicographic window queries (primary axis + `id` tiebreak), and
|
|
46
|
+
* exhaustion (short window, and the null-tail rule: NULL sort-value rows collect at the tail
|
|
47
|
+
* under the sort; a null can't anchor a continuation, so paging stops). The db round trip is
|
|
48
|
+
* injected through the pager's `options.db` seam via the house internals-cast pattern — no
|
|
49
|
+
* module mocking.
|
|
59
50
|
*/
|
|
60
51
|
var moment_1 = __importDefault(require("moment"));
|
|
61
|
-
var
|
|
62
|
-
var
|
|
52
|
+
var db_1 = require("@proteinjs/db");
|
|
53
|
+
var QueryCursorLoader_1 = require("../src/table/QueryCursorLoader");
|
|
54
|
+
// Load the reflection source graph so the house Serializer's custom serializers (moments)
|
|
55
|
+
// are registered — cursor encode/decode fidelity rides them.
|
|
56
|
+
require("../generated/index");
|
|
57
|
+
var table = { name: 'test_content' };
|
|
58
|
+
var sort = [{ field: 'lastActivityAt', desc: true }];
|
|
59
|
+
var createQuery = function () { return new db_1.QueryBuilder(table.name); };
|
|
60
|
+
var staged = { rows: [] };
|
|
61
|
+
var executed = [];
|
|
63
62
|
var stubDb = {
|
|
64
63
|
query: function (_table, qb) { return __awaiter(void 0, void 0, void 0, function () {
|
|
65
64
|
return __generator(this, function (_a) {
|
|
66
|
-
|
|
67
|
-
return [2 /*return*/,
|
|
65
|
+
executed.push(qb);
|
|
66
|
+
return [2 /*return*/, staged.rows];
|
|
68
67
|
});
|
|
69
68
|
}); },
|
|
70
69
|
};
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
var
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
var internals = function (loader) { return loader; };
|
|
70
|
+
var loaderWithStubDb = function (sortCriteria, query) {
|
|
71
|
+
if (query === void 0) { query = createQuery; }
|
|
72
|
+
var loader = new QueryCursorLoader_1.QueryCursorLoader(table, query, sortCriteria);
|
|
73
|
+
loader.pager.options = { db: stubDb };
|
|
74
|
+
return loader;
|
|
75
|
+
};
|
|
78
76
|
var graphNodes = function (qb) { return qb.graph.nodes().map(function (id) { return qb.graph.node(id); }); };
|
|
79
77
|
var conditionNodes = function (qb) { return graphNodes(qb).filter(function (node) { return (node === null || node === void 0 ? void 0 : node.type) === 'CONDITION'; }); };
|
|
80
78
|
var paginationNode = function (qb) { return graphNodes(qb).find(function (node) { return (node === null || node === void 0 ? void 0 : node.type) === 'PAGINATION'; }); };
|
|
@@ -83,11 +81,11 @@ var dated = function (id, at) { return ({
|
|
|
83
81
|
id: id,
|
|
84
82
|
created: (0, moment_1.default)(),
|
|
85
83
|
updated: (0, moment_1.default)(),
|
|
86
|
-
lastActivityAt: at ? (0, moment_1.default)(at) :
|
|
84
|
+
lastActivityAt: at ? (0, moment_1.default)(at) : null,
|
|
87
85
|
}); };
|
|
88
86
|
beforeEach(function () {
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
staged.rows = [];
|
|
88
|
+
executed.length = 0;
|
|
91
89
|
});
|
|
92
90
|
describe('reactQueryKeys', function () {
|
|
93
91
|
it('names the data set after the table and the query after its serialized query + sort', function () {
|
|
@@ -103,90 +101,119 @@ describe('reactQueryKeys', function () {
|
|
|
103
101
|
expect(resorted.reactQueryKeys.dataQueryKey).not.toBe(loader.reactQueryKeys.dataQueryKey);
|
|
104
102
|
});
|
|
105
103
|
});
|
|
106
|
-
describe('
|
|
107
|
-
it('the first window carries no cursor
|
|
108
|
-
var loader
|
|
109
|
-
var qb = internals(loader).buildWindowQuery(null, 30);
|
|
110
|
-
expect(conditionNodes(qb)).toHaveLength(0);
|
|
111
|
-
expect(paginationNode(qb)).toMatchObject({ start: 0, end: 30 });
|
|
112
|
-
expect(sortNodes(qb)).toHaveLength(1);
|
|
113
|
-
expect(sortNodes(qb)[0].criteria).toMatchObject({ field: 'lastActivityAt', desc: true });
|
|
114
|
-
});
|
|
115
|
-
it('a cursor becomes `field < cursor` on the primary sort field for a descending sort', function () {
|
|
116
|
-
var loader = new QueryCursorLoader_1.QueryCursorLoader(table, createQuery, sort);
|
|
117
|
-
var cursor = (0, moment_1.default)('2026-08-10T12:00:00.000Z');
|
|
118
|
-
var qb = internals(loader).buildWindowQuery(cursor, 30);
|
|
119
|
-
var conditions = conditionNodes(qb);
|
|
120
|
-
expect(conditions).toHaveLength(1);
|
|
121
|
-
expect(conditions[0]).toMatchObject({ field: 'lastActivityAt', operator: '<' });
|
|
122
|
-
expect(conditions[0].value).toBe(cursor);
|
|
123
|
-
expect(paginationNode(qb)).toMatchObject({ start: 0, end: 30 });
|
|
124
|
-
});
|
|
125
|
-
it('an ascending primary sort flips the cursor operator to `>`', function () {
|
|
126
|
-
var loader = new QueryCursorLoader_1.QueryCursorLoader(table, createQuery, [{ field: 'lastActivityAt', desc: false }]);
|
|
127
|
-
var qb = internals(loader).buildWindowQuery(5, 10);
|
|
128
|
-
expect(conditionNodes(qb)[0]).toMatchObject({ field: 'lastActivityAt', operator: '>', value: 5 });
|
|
129
|
-
});
|
|
130
|
-
it('every window builds on a FRESH query — cursor conditions never accumulate across windows', function () {
|
|
131
|
-
var loader = new QueryCursorLoader_1.QueryCursorLoader(table, createQuery, sort);
|
|
132
|
-
internals(loader).buildWindowQuery((0, moment_1.default)('2026-08-10T12:00:00.000Z'), 30);
|
|
133
|
-
var second = internals(loader).buildWindowQuery((0, moment_1.default)('2026-08-01T12:00:00.000Z'), 30);
|
|
134
|
-
expect(conditionNodes(second)).toHaveLength(1);
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
describe('deriveNextCursor — exhaustion', function () {
|
|
138
|
-
var loader = new QueryCursorLoader_1.QueryCursorLoader(table, createQuery, sort);
|
|
139
|
-
it('a short window is exhausted', function () {
|
|
140
|
-
expect(internals(loader).deriveNextCursor([dated('a', '2026-08-10T12:00:00.000Z')], 3)).toBeNull();
|
|
141
|
-
expect(internals(loader).deriveNextCursor([], 3)).toBeNull();
|
|
142
|
-
});
|
|
143
|
-
it('a full window anchors the next cursor at its tail', function () {
|
|
144
|
-
var rows = [
|
|
145
|
-
dated('a', '2026-08-10T12:00:00.000Z'),
|
|
146
|
-
dated('b', '2026-08-09T12:00:00.000Z'),
|
|
147
|
-
dated('c', '2026-08-08T12:00:00.000Z'),
|
|
148
|
-
];
|
|
149
|
-
var next = internals(loader).deriveNextCursor(rows, 3);
|
|
150
|
-
expect(next).toBe(rows[2].lastActivityAt);
|
|
151
|
-
});
|
|
152
|
-
it('a full window with a NULL cursor-field tail is exhausted (null rows collect at the tail; no anchor)', function () {
|
|
153
|
-
var rows = [dated('a', '2026-08-10T12:00:00.000Z'), dated('b', '2026-08-09T12:00:00.000Z'), dated('c', null)];
|
|
154
|
-
expect(internals(loader).deriveNextCursor(rows, 3)).toBeNull();
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
describe('loadWindow', function () {
|
|
158
|
-
it('returns the queried rows with the derived next cursor', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
159
|
-
var loader, rows, window;
|
|
104
|
+
describe('loadWindow — cursor threading', function () {
|
|
105
|
+
it('the first window carries no cursor conditions — the sort (with id tiebreak) and the window pagination', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
106
|
+
var loader, qb;
|
|
160
107
|
return __generator(this, function (_a) {
|
|
161
108
|
switch (_a.label) {
|
|
162
109
|
case 0:
|
|
163
|
-
loader =
|
|
110
|
+
loader = loaderWithStubDb(sort);
|
|
111
|
+
staged.rows = [];
|
|
112
|
+
return [4 /*yield*/, loader.loadWindow(null, 30)];
|
|
113
|
+
case 1:
|
|
114
|
+
_a.sent();
|
|
115
|
+
expect(executed).toHaveLength(1);
|
|
116
|
+
qb = executed[0];
|
|
117
|
+
expect(conditionNodes(qb)).toHaveLength(0);
|
|
118
|
+
expect(paginationNode(qb)).toMatchObject({ start: 0, end: 30 });
|
|
119
|
+
expect(sortNodes(qb).map(function (node) { return node.criteria; })).toEqual([
|
|
120
|
+
{ field: 'lastActivityAt', desc: true },
|
|
121
|
+
{ field: 'id', desc: false },
|
|
122
|
+
]);
|
|
123
|
+
return [2 /*return*/];
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}); });
|
|
127
|
+
it('a full window returns a string cursor; feeding it back threads the lexicographic continuation', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
128
|
+
var loader, rows, first, qb, conditions, past;
|
|
129
|
+
return __generator(this, function (_a) {
|
|
130
|
+
switch (_a.label) {
|
|
131
|
+
case 0:
|
|
132
|
+
loader = loaderWithStubDb(sort);
|
|
164
133
|
rows = [
|
|
165
134
|
dated('a', '2026-08-10T12:00:00.000Z'),
|
|
166
135
|
dated('b', '2026-08-09T12:00:00.000Z'),
|
|
167
136
|
dated('c', '2026-08-08T12:00:00.000Z'),
|
|
168
137
|
];
|
|
169
|
-
|
|
138
|
+
staged.rows = rows;
|
|
139
|
+
return [4 /*yield*/, loader.loadWindow(null, 3)];
|
|
140
|
+
case 1:
|
|
141
|
+
first = _a.sent();
|
|
142
|
+
expect(first.rows).toBe(rows);
|
|
143
|
+
expect(typeof first.nextCursor).toBe('string');
|
|
144
|
+
staged.rows = [];
|
|
145
|
+
return [4 /*yield*/, loader.loadWindow(first.nextCursor, 3)];
|
|
146
|
+
case 2:
|
|
147
|
+
_a.sent();
|
|
148
|
+
qb = executed[1];
|
|
149
|
+
conditions = conditionNodes(qb);
|
|
150
|
+
expect(conditions).toHaveLength(3);
|
|
151
|
+
past = conditions.find(function (node) { return node.operator === '<'; });
|
|
152
|
+
expect(past).toMatchObject({ field: 'lastActivityAt' });
|
|
153
|
+
expect(moment_1.default.isMoment(past.value)).toBe(true);
|
|
154
|
+
expect(past.value.toISOString()).toBe(rows[2].lastActivityAt.toISOString());
|
|
155
|
+
expect(conditions.find(function (node) { return node.operator === '='; })).toMatchObject({ field: 'lastActivityAt' });
|
|
156
|
+
expect(conditions.find(function (node) { return node.operator === '>'; })).toMatchObject({ field: 'id', value: 'c' });
|
|
157
|
+
return [2 /*return*/];
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}); });
|
|
161
|
+
it('every window builds on a FRESH query — cursor conditions never accumulate across windows', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
162
|
+
var loader, first, second;
|
|
163
|
+
return __generator(this, function (_a) {
|
|
164
|
+
switch (_a.label) {
|
|
165
|
+
case 0:
|
|
166
|
+
loader = loaderWithStubDb(sort);
|
|
167
|
+
staged.rows = [
|
|
168
|
+
dated('a', '2026-08-10T12:00:00.000Z'),
|
|
169
|
+
dated('b', '2026-08-09T12:00:00.000Z'),
|
|
170
|
+
dated('c', '2026-08-08T12:00:00.000Z'),
|
|
171
|
+
];
|
|
172
|
+
return [4 /*yield*/, loader.loadWindow(null, 3)];
|
|
173
|
+
case 1:
|
|
174
|
+
first = _a.sent();
|
|
175
|
+
staged.rows = [
|
|
176
|
+
dated('d', '2026-08-07T12:00:00.000Z'),
|
|
177
|
+
dated('e', '2026-08-06T12:00:00.000Z'),
|
|
178
|
+
dated('f', '2026-08-05T12:00:00.000Z'),
|
|
179
|
+
];
|
|
180
|
+
return [4 /*yield*/, loader.loadWindow(first.nextCursor, 3)];
|
|
181
|
+
case 2:
|
|
182
|
+
second = _a.sent();
|
|
183
|
+
staged.rows = [];
|
|
184
|
+
return [4 /*yield*/, loader.loadWindow(second.nextCursor, 3)];
|
|
185
|
+
case 3:
|
|
186
|
+
_a.sent();
|
|
187
|
+
expect(conditionNodes(executed[2])).toHaveLength(3);
|
|
188
|
+
return [2 /*return*/];
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}); });
|
|
192
|
+
});
|
|
193
|
+
describe('loadWindow — exhaustion', function () {
|
|
194
|
+
it('a short window is exhausted (null cursor)', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
195
|
+
var loader, window;
|
|
196
|
+
return __generator(this, function (_a) {
|
|
197
|
+
switch (_a.label) {
|
|
198
|
+
case 0:
|
|
199
|
+
loader = loaderWithStubDb(sort);
|
|
200
|
+
staged.rows = [dated('a', '2026-08-10T12:00:00.000Z')];
|
|
170
201
|
return [4 /*yield*/, loader.loadWindow(null, 3)];
|
|
171
202
|
case 1:
|
|
172
203
|
window = _a.sent();
|
|
173
|
-
expect(window.
|
|
174
|
-
expect(window.nextCursor).toBe(rows[2].lastActivityAt);
|
|
175
|
-
// The executed query is the built window query: pagination sized to the window.
|
|
176
|
-
expect(queries).toHaveLength(1);
|
|
177
|
-
expect(paginationNode(queries[0])).toMatchObject({ start: 0, end: 3 });
|
|
204
|
+
expect(window.nextCursor).toBeNull();
|
|
178
205
|
return [2 /*return*/];
|
|
179
206
|
}
|
|
180
207
|
});
|
|
181
208
|
}); });
|
|
182
|
-
it('
|
|
209
|
+
it('a full window with a NULL sort-value tail is exhausted (null rows collect at the tail; no anchor)', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
183
210
|
var loader, window;
|
|
184
211
|
return __generator(this, function (_a) {
|
|
185
212
|
switch (_a.label) {
|
|
186
213
|
case 0:
|
|
187
|
-
loader =
|
|
188
|
-
|
|
189
|
-
return [4 /*yield*/, loader.loadWindow(
|
|
214
|
+
loader = loaderWithStubDb(sort);
|
|
215
|
+
staged.rows = [dated('a', '2026-08-10T12:00:00.000Z'), dated('b', '2026-08-09T12:00:00.000Z'), dated('c', null)];
|
|
216
|
+
return [4 /*yield*/, loader.loadWindow(null, 3)];
|
|
190
217
|
case 1:
|
|
191
218
|
window = _a.sent();
|
|
192
219
|
expect(window.nextCursor).toBeNull();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryCursorLoader.test.js","sourceRoot":"","sources":["../../test/QueryCursorLoader.test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"QueryCursorLoader.test.js","sourceRoot":"","sources":["../../test/QueryCursorLoader.test.ts"],"names":[],"mappings":"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"}
|
package/generated/index.ts
CHANGED
|
@@ -16,7 +16,7 @@ import 'uuid';
|
|
|
16
16
|
/** Generate Source Graph */
|
|
17
17
|
|
|
18
18
|
const sourceGraph =
|
|
19
|
-
'{"options":{"directed":true,"multigraph":false,"compound":false},"nodes":[{"v":"@proteinjs/db-ui/QueryCursorLoader","value":{"packageName":"@proteinjs/db-ui","name":"QueryCursorLoader","filePath":"/home/runner/work/db/db/packages/ui/src/table/QueryCursorLoader.ts","qualifiedName":"@proteinjs/db-ui/QueryCursorLoader","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"reactQueryKeys","type":{"packageName":"@proteinjs/ui","name":"ReactQueryKeys","filePath":null,"qualifiedName":"@proteinjs/ui/ReactQueryKeys","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"sort","type":{"packageName":"","name":"SortCriteria<T>[]","filePath":null,"qualifiedName":"/SortCriteria<T>[]","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"table","type":{"packageName":"","name":"Table<T>","filePath":null,"qualifiedName":"/Table<T>","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"createQuery","type":{"packageName":"","name":"() => QueryBuilder<T>","filePath":null,"qualifiedName":"/() => QueryBuilder<T>","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"queryOptions","type":{"packageName":"","name":"QueryOptions<T>","filePath":null,"qualifiedName":"/QueryOptions<T>","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"private"}],"methods":[{"name":"loadWindow","returnType":{"packageName":"","name":"Promise<CursorWindow<T>>","filePath":null,"qualifiedName":"/Promise<CursorWindow<T>>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"cursor","type":{"packageName":"","name":"CursorValue | null","filePath":null,"qualifiedName":"/CursorValue | null","typeParameters":null,"directParents":null}},{"name":"windowSize","type":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null}}]},{"name":"buildWindowQuery","returnType":{"packageName":"","name":"QueryBuilder<T>","filePath":null,"qualifiedName":"/QueryBuilder<T>","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"cursor","type":{"packageName":"","name":"CursorValue | null","filePath":null,"qualifiedName":"/CursorValue | null","typeParameters":null,"directParents":null}},{"name":"windowSize","type":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null}}]},{"name":"deriveNextCursor","returnType":{"packageName":"","name":"CursorValue | null","filePath":null,"qualifiedName":"/CursorValue | null","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"rows","type":{"packageName":"","name":"T[]","filePath":null,"qualifiedName":"/T[]","typeParameters":null,"directParents":null}},{"name":"windowSize","type":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null}}]}],"typeParameters":["/T extends Record"],"directParentInterfaces":[{"packageName":"@proteinjs/ui","name":"CursorLoader","filePath":null,"qualifiedName":"@proteinjs/ui/CursorLoader","properties":[],"methods":[],"typeParameters":["/T"],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/ui/CursorLoader"},{"v":"@proteinjs/db-ui/QueryTableLoader","value":{"packageName":"@proteinjs/db-ui","name":"QueryTableLoader","filePath":"/home/runner/work/db/db/packages/ui/src/table/QueryTableLoader.ts","qualifiedName":"@proteinjs/db-ui/QueryTableLoader","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"rowCountQb","type":{"packageName":"","name":"QueryBuilder<T>","filePath":null,"qualifiedName":"/QueryBuilder<T>","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"paginationQb","type":{"packageName":"","name":"QueryBuilder<T>","filePath":null,"qualifiedName":"/QueryBuilder<T>","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"reactQueryKeys","type":{"packageName":"","name":"TableLoader<T>[\'reactQueryKeys\']","filePath":null,"qualifiedName":"/TableLoader<T>[\'reactQueryKeys\']","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"table","type":{"packageName":"","name":"Table<T>","filePath":null,"qualifiedName":"/Table<T>","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"query","type":{"packageName":"","name":"Query<T>","filePath":null,"qualifiedName":"/Query<T>","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"sort","type":{"packageName":"","name":"SortCriteria<T>[]","filePath":null,"qualifiedName":"/SortCriteria<T>[]","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"queryOptions","type":{"packageName":"","name":"QueryOptions<T>","filePath":null,"qualifiedName":"/QueryOptions<T>","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"private"}],"methods":[{"name":"load","returnType":{"packageName":"","name":"Promise<RowWindow<T>>","filePath":null,"qualifiedName":"/Promise<RowWindow<T>>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"startIndex","type":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null}},{"name":"endIndex","type":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null}},{"name":"skipRowCount","type":{"packageName":"","name":"boolean","filePath":null,"qualifiedName":"/boolean","typeParameters":null,"directParents":null}}]}],"typeParameters":["/T extends Record"],"directParentInterfaces":[{"packageName":"@proteinjs/ui","name":"TableLoader","filePath":null,"qualifiedName":"@proteinjs/ui/TableLoader","properties":[],"methods":[],"typeParameters":["/T"],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/ui/TableLoader"},{"v":"@proteinjs/db-ui/RecordFormCustomization","value":{"packageName":"@proteinjs/db-ui","name":"RecordFormCustomization","filePath":"/home/runner/work/db/db/packages/ui/src/form/RecordFormCustomization.tsx","qualifiedName":"@proteinjs/db-ui/RecordFormCustomization","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"getFormButtons","returnType":{"packageName":"","name":"FormButtons<any>","filePath":null,"qualifiedName":"/FormButtons<any>","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"record","type":{"packageName":"","name":"any","filePath":null,"qualifiedName":"/any","typeParameters":null,"directParents":null}},{"name":"defaultFormButtons","type":{"packageName":"","name":"FormButtons<any>","filePath":null,"qualifiedName":"/FormButtons<any>","typeParameters":null,"directParents":null}}]},{"name":"getFieldLayout","returnType":{"packageName":"","name":"string[] | string[][]","filePath":null,"qualifiedName":"/string[] | string[][]","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"record","type":{"packageName":"","name":"any","filePath":null,"qualifiedName":"/any","typeParameters":null,"directParents":null}},{"name":"defaultFieldLayout","type":{"packageName":"","name":"string[] | string[][]","filePath":null,"qualifiedName":"/string[] | string[][]","typeParameters":null,"directParents":null}}]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/reflection","name":"Loadable","filePath":null,"qualifiedName":"@proteinjs/reflection/Loadable","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/reflection/Loadable"},{"v":"@proteinjs/db-ui/hashGeneratorPage","value":{"packageName":"@proteinjs/db-ui","name":"hashGeneratorPage","filePath":"/home/runner/work/db/db/packages/ui/src/pages/HashGeneratorPage.tsx","qualifiedName":"@proteinjs/db-ui/hashGeneratorPage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/ui/Page"},{"v":"@proteinjs/db-ui/recordFormPage","value":{"packageName":"@proteinjs/db-ui","name":"recordFormPage","filePath":"/home/runner/work/db/db/packages/ui/src/pages/RecordFormPage.tsx","qualifiedName":"@proteinjs/db-ui/recordFormPage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/db-ui/recordTablePage","value":{"packageName":"@proteinjs/db-ui","name":"recordTablePage","filePath":"/home/runner/work/db/db/packages/ui/src/pages/RecordTablePage.tsx","qualifiedName":"@proteinjs/db-ui/recordTablePage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/db-ui/tablesPage","value":{"packageName":"@proteinjs/db-ui","name":"tablesPage","filePath":"/home/runner/work/db/db/packages/ui/src/pages/TablesPage.tsx","qualifiedName":"@proteinjs/db-ui/tablesPage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/db-ui/uuidGeneratorPage","value":{"packageName":"@proteinjs/db-ui","name":"uuidGeneratorPage","filePath":"/home/runner/work/db/db/packages/ui/src/pages/UuidGeneratorPage.tsx","qualifiedName":"@proteinjs/db-ui/uuidGeneratorPage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/db-ui/SpecificTableProps"},{"v":"@proteinjs/db-ui/MigrationRecordFormCustomization","value":{"packageName":"@proteinjs/db-ui","name":"MigrationRecordFormCustomization","filePath":"/home/runner/work/db/db/packages/ui/src/form/customizations/MigrationRecordFormCustomization.tsx","qualifiedName":"@proteinjs/db-ui/MigrationRecordFormCustomization","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"table","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"getFormButtons","returnType":{"packageName":"","name":"FormButtons<any>","filePath":null,"qualifiedName":"/FormButtons<any>","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"migration","type":{"packageName":"@proteinjs/db","name":"Migration","filePath":null,"qualifiedName":"@proteinjs/db/Migration","typeParameters":null,"directParents":null}},{"name":"defaultFormButtons","type":{"packageName":"","name":"FormButtons<any>","filePath":null,"qualifiedName":"/FormButtons<any>","typeParameters":null,"directParents":null}}]}],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[{"packageName":"@proteinjs/db-ui","name":"RecordFormCustomization","filePath":null,"qualifiedName":"@proteinjs/db-ui/RecordFormCustomization","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[]}],"sourceType":2}}],"edges":[{"v":"@proteinjs/db-ui/QueryCursorLoader","w":"@proteinjs/ui/CursorLoader","value":"implements interface"},{"v":"@proteinjs/db-ui/QueryTableLoader","w":"@proteinjs/ui/TableLoader","value":"implements interface"},{"v":"@proteinjs/db-ui/RecordFormCustomization","w":"@proteinjs/reflection/Loadable","value":"implements interface"},{"v":"@proteinjs/db-ui/hashGeneratorPage","w":"@proteinjs/ui/Page","value":"has type"},{"v":"@proteinjs/db-ui/recordFormPage","w":"@proteinjs/ui/Page","value":"has type"},{"v":"@proteinjs/db-ui/recordTablePage","w":"@proteinjs/ui/Page","value":"has type"},{"v":"@proteinjs/db-ui/tablesPage","w":"@proteinjs/ui/Page","value":"has type"},{"v":"@proteinjs/db-ui/uuidGeneratorPage","w":"@proteinjs/ui/Page","value":"has type"},{"v":"@proteinjs/db-ui/MigrationRecordFormCustomization","w":"@proteinjs/db-ui/RecordFormCustomization","value":"extends class"}]}';
|
|
19
|
+
'{"options":{"directed":true,"multigraph":false,"compound":false},"nodes":[{"v":"@proteinjs/db-ui/QueryCursorLoader","value":{"packageName":"@proteinjs/db-ui","name":"QueryCursorLoader","filePath":"/home/runner/work/db/db/packages/ui/src/table/QueryCursorLoader.ts","qualifiedName":"@proteinjs/db-ui/QueryCursorLoader","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"reactQueryKeys","type":{"packageName":"@proteinjs/ui","name":"ReactQueryKeys","filePath":null,"qualifiedName":"@proteinjs/ui/ReactQueryKeys","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"pager","type":{"packageName":"","name":"CursorWindowPager<T>","filePath":null,"qualifiedName":"/CursorWindowPager<T>","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"}],"methods":[{"name":"loadWindow","returnType":{"packageName":"","name":"Promise<CursorWindow<T>>","filePath":null,"qualifiedName":"/Promise<CursorWindow<T>>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"cursor","type":{"packageName":"","name":"CursorValue | null","filePath":null,"qualifiedName":"/CursorValue | null","typeParameters":null,"directParents":null}},{"name":"windowSize","type":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null}}]}],"typeParameters":["/T extends Record"],"directParentInterfaces":[{"packageName":"@proteinjs/ui","name":"CursorLoader","filePath":null,"qualifiedName":"@proteinjs/ui/CursorLoader","properties":[],"methods":[],"typeParameters":["/T"],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/ui/CursorLoader"},{"v":"@proteinjs/db-ui/QueryTableLoader","value":{"packageName":"@proteinjs/db-ui","name":"QueryTableLoader","filePath":"/home/runner/work/db/db/packages/ui/src/table/QueryTableLoader.ts","qualifiedName":"@proteinjs/db-ui/QueryTableLoader","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"rowCountQb","type":{"packageName":"","name":"QueryBuilder<T>","filePath":null,"qualifiedName":"/QueryBuilder<T>","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"paginationQb","type":{"packageName":"","name":"QueryBuilder<T>","filePath":null,"qualifiedName":"/QueryBuilder<T>","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"reactQueryKeys","type":{"packageName":"","name":"TableLoader<T>[\'reactQueryKeys\']","filePath":null,"qualifiedName":"/TableLoader<T>[\'reactQueryKeys\']","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"table","type":{"packageName":"","name":"Table<T>","filePath":null,"qualifiedName":"/Table<T>","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"query","type":{"packageName":"","name":"Query<T>","filePath":null,"qualifiedName":"/Query<T>","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"sort","type":{"packageName":"","name":"SortCriteria<T>[]","filePath":null,"qualifiedName":"/SortCriteria<T>[]","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"queryOptions","type":{"packageName":"","name":"QueryOptions<T>","filePath":null,"qualifiedName":"/QueryOptions<T>","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"private"}],"methods":[{"name":"load","returnType":{"packageName":"","name":"Promise<RowWindow<T>>","filePath":null,"qualifiedName":"/Promise<RowWindow<T>>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"startIndex","type":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null}},{"name":"endIndex","type":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null}},{"name":"skipRowCount","type":{"packageName":"","name":"boolean","filePath":null,"qualifiedName":"/boolean","typeParameters":null,"directParents":null}}]}],"typeParameters":["/T extends Record"],"directParentInterfaces":[{"packageName":"@proteinjs/ui","name":"TableLoader","filePath":null,"qualifiedName":"@proteinjs/ui/TableLoader","properties":[],"methods":[],"typeParameters":["/T"],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/ui/TableLoader"},{"v":"@proteinjs/db-ui/RecordFormCustomization","value":{"packageName":"@proteinjs/db-ui","name":"RecordFormCustomization","filePath":"/home/runner/work/db/db/packages/ui/src/form/RecordFormCustomization.tsx","qualifiedName":"@proteinjs/db-ui/RecordFormCustomization","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"getFormButtons","returnType":{"packageName":"","name":"FormButtons<any>","filePath":null,"qualifiedName":"/FormButtons<any>","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"record","type":{"packageName":"","name":"any","filePath":null,"qualifiedName":"/any","typeParameters":null,"directParents":null}},{"name":"defaultFormButtons","type":{"packageName":"","name":"FormButtons<any>","filePath":null,"qualifiedName":"/FormButtons<any>","typeParameters":null,"directParents":null}}]},{"name":"getFieldLayout","returnType":{"packageName":"","name":"string[] | string[][]","filePath":null,"qualifiedName":"/string[] | string[][]","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"record","type":{"packageName":"","name":"any","filePath":null,"qualifiedName":"/any","typeParameters":null,"directParents":null}},{"name":"defaultFieldLayout","type":{"packageName":"","name":"string[] | string[][]","filePath":null,"qualifiedName":"/string[] | string[][]","typeParameters":null,"directParents":null}}]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/reflection","name":"Loadable","filePath":null,"qualifiedName":"@proteinjs/reflection/Loadable","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/reflection/Loadable"},{"v":"@proteinjs/db-ui/hashGeneratorPage","value":{"packageName":"@proteinjs/db-ui","name":"hashGeneratorPage","filePath":"/home/runner/work/db/db/packages/ui/src/pages/HashGeneratorPage.tsx","qualifiedName":"@proteinjs/db-ui/hashGeneratorPage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/ui/Page"},{"v":"@proteinjs/db-ui/recordFormPage","value":{"packageName":"@proteinjs/db-ui","name":"recordFormPage","filePath":"/home/runner/work/db/db/packages/ui/src/pages/RecordFormPage.tsx","qualifiedName":"@proteinjs/db-ui/recordFormPage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/db-ui/recordTablePage","value":{"packageName":"@proteinjs/db-ui","name":"recordTablePage","filePath":"/home/runner/work/db/db/packages/ui/src/pages/RecordTablePage.tsx","qualifiedName":"@proteinjs/db-ui/recordTablePage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/db-ui/tablesPage","value":{"packageName":"@proteinjs/db-ui","name":"tablesPage","filePath":"/home/runner/work/db/db/packages/ui/src/pages/TablesPage.tsx","qualifiedName":"@proteinjs/db-ui/tablesPage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/db-ui/uuidGeneratorPage","value":{"packageName":"@proteinjs/db-ui","name":"uuidGeneratorPage","filePath":"/home/runner/work/db/db/packages/ui/src/pages/UuidGeneratorPage.tsx","qualifiedName":"@proteinjs/db-ui/uuidGeneratorPage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/db-ui/SpecificTableProps"},{"v":"@proteinjs/db-ui/MigrationRecordFormCustomization","value":{"packageName":"@proteinjs/db-ui","name":"MigrationRecordFormCustomization","filePath":"/home/runner/work/db/db/packages/ui/src/form/customizations/MigrationRecordFormCustomization.tsx","qualifiedName":"@proteinjs/db-ui/MigrationRecordFormCustomization","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"table","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"getFormButtons","returnType":{"packageName":"","name":"FormButtons<any>","filePath":null,"qualifiedName":"/FormButtons<any>","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"migration","type":{"packageName":"@proteinjs/db","name":"Migration","filePath":null,"qualifiedName":"@proteinjs/db/Migration","typeParameters":null,"directParents":null}},{"name":"defaultFormButtons","type":{"packageName":"","name":"FormButtons<any>","filePath":null,"qualifiedName":"/FormButtons<any>","typeParameters":null,"directParents":null}}]}],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[{"packageName":"@proteinjs/db-ui","name":"RecordFormCustomization","filePath":null,"qualifiedName":"@proteinjs/db-ui/RecordFormCustomization","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[]}],"sourceType":2}}],"edges":[{"v":"@proteinjs/db-ui/QueryCursorLoader","w":"@proteinjs/ui/CursorLoader","value":"implements interface"},{"v":"@proteinjs/db-ui/QueryTableLoader","w":"@proteinjs/ui/TableLoader","value":"implements interface"},{"v":"@proteinjs/db-ui/RecordFormCustomization","w":"@proteinjs/reflection/Loadable","value":"implements interface"},{"v":"@proteinjs/db-ui/hashGeneratorPage","w":"@proteinjs/ui/Page","value":"has type"},{"v":"@proteinjs/db-ui/recordFormPage","w":"@proteinjs/ui/Page","value":"has type"},{"v":"@proteinjs/db-ui/recordTablePage","w":"@proteinjs/ui/Page","value":"has type"},{"v":"@proteinjs/db-ui/tablesPage","w":"@proteinjs/ui/Page","value":"has type"},{"v":"@proteinjs/db-ui/uuidGeneratorPage","w":"@proteinjs/ui/Page","value":"has type"},{"v":"@proteinjs/db-ui/MigrationRecordFormCustomization","w":"@proteinjs/db-ui/RecordFormCustomization","value":"extends class"}]}';
|
|
20
20
|
|
|
21
21
|
/** Generate Source Links */
|
|
22
22
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proteinjs/db-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"description": "Db ui components",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@emotion/styled": "11.11.0",
|
|
27
27
|
"@mui/icons-material": "5.14.11",
|
|
28
28
|
"@mui/material": "5.14.11",
|
|
29
|
-
"@proteinjs/db": "^1.
|
|
29
|
+
"@proteinjs/db": "^1.32.0",
|
|
30
30
|
"@proteinjs/reflection": "^1.1.12",
|
|
31
31
|
"@proteinjs/ui": "^4.5.0",
|
|
32
32
|
"@proteinjs/util": "^1.6.1",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
},
|
|
55
55
|
"main": "./dist/generated/index.js",
|
|
56
56
|
"types": "./dist/generated/index.d.ts",
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "edfed2d7826c7e42ddc0ae84bf97cda11614c1f0"
|
|
58
58
|
}
|
|
@@ -1,70 +1,50 @@
|
|
|
1
|
-
import { QueryBuilder, QueryOptions, Record, SortCriteria, Table
|
|
1
|
+
import { CursorWindowPager, QueryBuilder, QueryOptions, Record, SortCriteria, Table } from '@proteinjs/db';
|
|
2
2
|
import { CursorLoader, CursorValue, CursorWindow, ReactQueryKeys } from '@proteinjs/ui';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* `CursorLoader` over the
|
|
6
|
-
*
|
|
7
|
-
* on a fresh build of the base query, so
|
|
8
|
-
* shift the window frame
|
|
9
|
-
*
|
|
5
|
+
* `CursorLoader` over the db-owned cursor-window machinery (`CursorWindowPager`): each window
|
|
6
|
+
* carries a lexicographic continuation past the anchor row — the primary sort axes plus a
|
|
7
|
+
* unique `id` tiebreak — and `paginate(0, windowSize)` on a fresh build of the base query, so
|
|
8
|
+
* rows created or removed while paging can never shift the window frame, and ties on the sort
|
|
9
|
+
* axis can never skip or duplicate boundary rows. Cursors are the pager's anchors encoded as
|
|
10
|
+
* strings (house `Serializer`, so dates/moments survive react-query page params).
|
|
10
11
|
*
|
|
11
12
|
* `dataKey` is the table name — table-level invalidation (`useTableMutation`) reaches every
|
|
12
13
|
* cursor query over it; `dataQueryKey` is the serialized query + sort.
|
|
13
14
|
*/
|
|
14
15
|
export class QueryCursorLoader<T extends Record> implements CursorLoader<T> {
|
|
15
16
|
reactQueryKeys: ReactQueryKeys;
|
|
16
|
-
private
|
|
17
|
+
private pager: CursorWindowPager<T>;
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* @param table the table to load windows from
|
|
20
21
|
* @param createQuery factory producing a FRESH conditions-only QueryBuilder per call —
|
|
21
|
-
* builders are mutable, so every window builds its own to hang the cursor
|
|
22
|
+
* builders are mutable, so every window builds its own to hang the cursor conditions,
|
|
22
23
|
* sort, and pagination on
|
|
23
24
|
* @param sort the sort criteria to apply to every window; the primary criterion is the
|
|
24
|
-
* cursor axis
|
|
25
|
+
* cursor axis (the pager appends the `id` tiebreak)
|
|
25
26
|
* @param queryOptions query options passed through to every window query
|
|
26
27
|
*/
|
|
27
28
|
constructor(
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
table: Table<T>,
|
|
30
|
+
createQuery: () => QueryBuilder<T>,
|
|
30
31
|
sort?: SortCriteria<T>[],
|
|
31
|
-
|
|
32
|
+
queryOptions?: QueryOptions<T>
|
|
32
33
|
) {
|
|
33
|
-
|
|
34
|
+
const effectiveSort = sort ? sort : [{ field: 'created' as keyof T, desc: true }];
|
|
35
|
+
this.pager = new CursorWindowPager<T>(table, createQuery, effectiveSort, { queryOptions });
|
|
34
36
|
this.reactQueryKeys = {
|
|
35
|
-
dataKey:
|
|
36
|
-
dataQueryKey: JSON.stringify({ query:
|
|
37
|
+
dataKey: table.name,
|
|
38
|
+
dataQueryKey: JSON.stringify({ query: createQuery(), sort: effectiveSort }),
|
|
37
39
|
};
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
async loadWindow(cursor: CursorValue | null, windowSize: number): Promise<CursorWindow<T>> {
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
return {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const qb = this.createQuery();
|
|
48
|
-
const primarySort = this.sort[0];
|
|
49
|
-
if (cursor !== null) {
|
|
50
|
-
qb.condition({
|
|
51
|
-
field: primarySort.field,
|
|
52
|
-
operator: primarySort.desc ? '<' : '>',
|
|
53
|
-
value: cursor as T[keyof T],
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
return qb.sort(this.sort).paginate({ start: 0, end: windowSize });
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
private deriveNextCursor(rows: T[], windowSize: number): CursorValue | null {
|
|
60
|
-
// A short window means the data set is exhausted; a full one implies more may exist —
|
|
61
|
-
// the next (short or empty) window settles it.
|
|
62
|
-
if (rows.length < windowSize) {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
// NULL cursor-field rows collect at the tail under the sort, and a null tail can't
|
|
66
|
-
// anchor a cursor: the data set's dated rows are exhausted, so paging stops here.
|
|
67
|
-
const tail = rows[rows.length - 1][this.sort[0].field];
|
|
68
|
-
return tail == null ? null : (tail as unknown as CursorValue);
|
|
43
|
+
const anchor = cursor === null ? null : CursorWindowPager.decodeAnchor(cursor as string);
|
|
44
|
+
const window = await this.pager.loadWindow(anchor, windowSize);
|
|
45
|
+
return {
|
|
46
|
+
rows: window.rows,
|
|
47
|
+
nextCursor: window.nextAnchor ? CursorWindowPager.encodeAnchor(window.nextAnchor) : null,
|
|
48
|
+
};
|
|
69
49
|
}
|
|
70
50
|
}
|
|
@@ -1,35 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* QueryCursorLoader (src/table/QueryCursorLoader.ts)
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* the
|
|
2
|
+
* QueryCursorLoader (src/table/QueryCursorLoader.ts) as the thin `CursorLoader` adapter over
|
|
3
|
+
* the db-owned `CursorWindowPager`: react-query key derivation, string-cursor encode/decode
|
|
4
|
+
* threading into the pager's lexicographic window queries (primary axis + `id` tiebreak), and
|
|
5
|
+
* exhaustion (short window, and the null-tail rule: NULL sort-value rows collect at the tail
|
|
6
|
+
* under the sort; a null can't anchor a continuation, so paging stops). The db round trip is
|
|
7
|
+
* injected through the pager's `options.db` seam via the house internals-cast pattern — no
|
|
8
|
+
* module mocking.
|
|
7
9
|
*/
|
|
8
10
|
import moment from 'moment';
|
|
9
|
-
|
|
10
|
-
const stagedRows: { rows: unknown[] } = { rows: [] };
|
|
11
|
-
const queries: unknown[] = [];
|
|
12
|
-
const stubDb = {
|
|
13
|
-
query: async (_table: unknown, qb: unknown) => {
|
|
14
|
-
queries.push(qb);
|
|
15
|
-
return stagedRows.rows;
|
|
16
|
-
},
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
jest.mock('@proteinjs/db', () => ({
|
|
20
|
-
...jest.requireActual('@proteinjs/db'),
|
|
21
|
-
getDb: () => stubDb,
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
import { QueryBuilder, SortCriteria, Table } from '@proteinjs/db';
|
|
25
|
-
import { CursorValue } from '@proteinjs/ui';
|
|
11
|
+
import { Db, QueryBuilder, SortCriteria, Table } from '@proteinjs/db';
|
|
26
12
|
import { QueryCursorLoader } from '../src/table/QueryCursorLoader';
|
|
13
|
+
// Load the reflection source graph so the house Serializer's custom serializers (moments)
|
|
14
|
+
// are registered — cursor encode/decode fidelity rides them.
|
|
15
|
+
import '../generated/index';
|
|
27
16
|
|
|
28
17
|
type Row = {
|
|
29
18
|
id: string;
|
|
30
19
|
created: moment.Moment;
|
|
31
20
|
updated: moment.Moment;
|
|
32
|
-
lastActivityAt?: moment.Moment;
|
|
21
|
+
lastActivityAt?: moment.Moment | null;
|
|
33
22
|
isPinned?: boolean;
|
|
34
23
|
};
|
|
35
24
|
|
|
@@ -37,13 +26,23 @@ const table = { name: 'test_content' } as Table<Row>;
|
|
|
37
26
|
const sort: SortCriteria<Row>[] = [{ field: 'lastActivityAt', desc: true }];
|
|
38
27
|
const createQuery = () => new QueryBuilder<Row>(table.name);
|
|
39
28
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
29
|
+
const staged: { rows: Row[] } = { rows: [] };
|
|
30
|
+
const executed: QueryBuilder<Row>[] = [];
|
|
31
|
+
const stubDb = {
|
|
32
|
+
query: async (_table: unknown, qb: QueryBuilder<Row>) => {
|
|
33
|
+
executed.push(qb);
|
|
34
|
+
return staged.rows;
|
|
35
|
+
},
|
|
36
|
+
} as unknown as Db;
|
|
37
|
+
|
|
38
|
+
/** House pattern: private internals reachable via a typed cast on the instance. */
|
|
39
|
+
type LoaderInternals = { pager: { options?: { db?: Db } } };
|
|
45
40
|
|
|
46
|
-
const
|
|
41
|
+
const loaderWithStubDb = (sortCriteria?: SortCriteria<Row>[], query: () => QueryBuilder<Row> = createQuery) => {
|
|
42
|
+
const loader = new QueryCursorLoader<Row>(table, query, sortCriteria);
|
|
43
|
+
(loader as unknown as LoaderInternals).pager.options = { db: stubDb };
|
|
44
|
+
return loader;
|
|
45
|
+
};
|
|
47
46
|
|
|
48
47
|
const graphNodes = (qb: QueryBuilder<Row>): any[] => qb.graph.nodes().map((id: string) => qb.graph.node(id));
|
|
49
48
|
const conditionNodes = (qb: QueryBuilder<Row>) => graphNodes(qb).filter((node) => node?.type === 'CONDITION');
|
|
@@ -54,12 +53,12 @@ const dated = (id: string, at: string | null): Row => ({
|
|
|
54
53
|
id,
|
|
55
54
|
created: moment(),
|
|
56
55
|
updated: moment(),
|
|
57
|
-
lastActivityAt: at ? moment(at) :
|
|
56
|
+
lastActivityAt: at ? moment(at) : null,
|
|
58
57
|
});
|
|
59
58
|
|
|
60
59
|
beforeEach(() => {
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
staged.rows = [];
|
|
61
|
+
executed.length = 0;
|
|
63
62
|
});
|
|
64
63
|
|
|
65
64
|
describe('reactQueryKeys', () => {
|
|
@@ -81,86 +80,80 @@ describe('reactQueryKeys', () => {
|
|
|
81
80
|
});
|
|
82
81
|
});
|
|
83
82
|
|
|
84
|
-
describe('
|
|
85
|
-
it('the first window carries no cursor
|
|
86
|
-
const loader =
|
|
87
|
-
|
|
83
|
+
describe('loadWindow — cursor threading', () => {
|
|
84
|
+
it('the first window carries no cursor conditions — the sort (with id tiebreak) and the window pagination', async () => {
|
|
85
|
+
const loader = loaderWithStubDb(sort);
|
|
86
|
+
staged.rows = [];
|
|
87
|
+
await loader.loadWindow(null, 30);
|
|
88
|
+
expect(executed).toHaveLength(1);
|
|
89
|
+
const qb = executed[0];
|
|
88
90
|
expect(conditionNodes(qb)).toHaveLength(0);
|
|
89
91
|
expect(paginationNode(qb)).toMatchObject({ start: 0, end: 30 });
|
|
90
|
-
expect(sortNodes(qb)).
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
it('a cursor becomes `field < cursor` on the primary sort field for a descending sort', () => {
|
|
95
|
-
const loader = new QueryCursorLoader<Row>(table, createQuery, sort);
|
|
96
|
-
const cursor = moment('2026-08-10T12:00:00.000Z');
|
|
97
|
-
const qb = internals(loader).buildWindowQuery(cursor, 30);
|
|
98
|
-
const conditions = conditionNodes(qb);
|
|
99
|
-
expect(conditions).toHaveLength(1);
|
|
100
|
-
expect(conditions[0]).toMatchObject({ field: 'lastActivityAt', operator: '<' });
|
|
101
|
-
expect(conditions[0].value).toBe(cursor);
|
|
102
|
-
expect(paginationNode(qb)).toMatchObject({ start: 0, end: 30 });
|
|
92
|
+
expect(sortNodes(qb).map((node) => node.criteria)).toEqual([
|
|
93
|
+
{ field: 'lastActivityAt', desc: true },
|
|
94
|
+
{ field: 'id', desc: false },
|
|
95
|
+
]);
|
|
103
96
|
});
|
|
104
97
|
|
|
105
|
-
it('
|
|
106
|
-
const loader =
|
|
107
|
-
const qb = internals(loader).buildWindowQuery(5, 10);
|
|
108
|
-
expect(conditionNodes(qb)[0]).toMatchObject({ field: 'lastActivityAt', operator: '>', value: 5 });
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('every window builds on a FRESH query — cursor conditions never accumulate across windows', () => {
|
|
112
|
-
const loader = new QueryCursorLoader<Row>(table, createQuery, sort);
|
|
113
|
-
internals(loader).buildWindowQuery(moment('2026-08-10T12:00:00.000Z'), 30);
|
|
114
|
-
const second = internals(loader).buildWindowQuery(moment('2026-08-01T12:00:00.000Z'), 30);
|
|
115
|
-
expect(conditionNodes(second)).toHaveLength(1);
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
describe('deriveNextCursor — exhaustion', () => {
|
|
120
|
-
const loader = new QueryCursorLoader<Row>(table, createQuery, sort);
|
|
121
|
-
|
|
122
|
-
it('a short window is exhausted', () => {
|
|
123
|
-
expect(internals(loader).deriveNextCursor([dated('a', '2026-08-10T12:00:00.000Z')], 3)).toBeNull();
|
|
124
|
-
expect(internals(loader).deriveNextCursor([], 3)).toBeNull();
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('a full window anchors the next cursor at its tail', () => {
|
|
98
|
+
it('a full window returns a string cursor; feeding it back threads the lexicographic continuation', async () => {
|
|
99
|
+
const loader = loaderWithStubDb(sort);
|
|
128
100
|
const rows = [
|
|
129
101
|
dated('a', '2026-08-10T12:00:00.000Z'),
|
|
130
102
|
dated('b', '2026-08-09T12:00:00.000Z'),
|
|
131
103
|
dated('c', '2026-08-08T12:00:00.000Z'),
|
|
132
104
|
];
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
105
|
+
staged.rows = rows;
|
|
106
|
+
const first = await loader.loadWindow(null, 3);
|
|
107
|
+
expect(first.rows).toBe(rows);
|
|
108
|
+
expect(typeof first.nextCursor).toBe('string');
|
|
109
|
+
|
|
110
|
+
staged.rows = [];
|
|
111
|
+
await loader.loadWindow(first.nextCursor, 3);
|
|
112
|
+
const qb = executed[1];
|
|
113
|
+
// Past-on-axis OR (equal-on-axis AND past-on-id), anchored at the tail row 'c' — with the
|
|
114
|
+
// moment surviving the string cursor round trip.
|
|
115
|
+
const conditions = conditionNodes(qb);
|
|
116
|
+
expect(conditions).toHaveLength(3);
|
|
117
|
+
const past = conditions.find((node) => node.operator === '<');
|
|
118
|
+
expect(past).toMatchObject({ field: 'lastActivityAt' });
|
|
119
|
+
expect(moment.isMoment(past.value)).toBe(true);
|
|
120
|
+
expect(past.value.toISOString()).toBe(rows[2].lastActivityAt!.toISOString());
|
|
121
|
+
expect(conditions.find((node) => node.operator === '=')).toMatchObject({ field: 'lastActivityAt' });
|
|
122
|
+
expect(conditions.find((node) => node.operator === '>')).toMatchObject({ field: 'id', value: 'c' });
|
|
140
123
|
});
|
|
141
|
-
});
|
|
142
124
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const rows = [
|
|
125
|
+
it('every window builds on a FRESH query — cursor conditions never accumulate across windows', async () => {
|
|
126
|
+
const loader = loaderWithStubDb(sort);
|
|
127
|
+
staged.rows = [
|
|
147
128
|
dated('a', '2026-08-10T12:00:00.000Z'),
|
|
148
129
|
dated('b', '2026-08-09T12:00:00.000Z'),
|
|
149
130
|
dated('c', '2026-08-08T12:00:00.000Z'),
|
|
150
131
|
];
|
|
151
|
-
|
|
132
|
+
const first = await loader.loadWindow(null, 3);
|
|
133
|
+
staged.rows = [
|
|
134
|
+
dated('d', '2026-08-07T12:00:00.000Z'),
|
|
135
|
+
dated('e', '2026-08-06T12:00:00.000Z'),
|
|
136
|
+
dated('f', '2026-08-05T12:00:00.000Z'),
|
|
137
|
+
];
|
|
138
|
+
const second = await loader.loadWindow(first.nextCursor, 3);
|
|
139
|
+
staged.rows = [];
|
|
140
|
+
await loader.loadWindow(second.nextCursor, 3);
|
|
141
|
+
expect(conditionNodes(executed[2])).toHaveLength(3);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
describe('loadWindow — exhaustion', () => {
|
|
146
|
+
it('a short window is exhausted (null cursor)', async () => {
|
|
147
|
+
const loader = loaderWithStubDb(sort);
|
|
148
|
+
staged.rows = [dated('a', '2026-08-10T12:00:00.000Z')];
|
|
152
149
|
const window = await loader.loadWindow(null, 3);
|
|
153
|
-
expect(window.
|
|
154
|
-
expect(window.nextCursor).toBe(rows[2].lastActivityAt);
|
|
155
|
-
// The executed query is the built window query: pagination sized to the window.
|
|
156
|
-
expect(queries).toHaveLength(1);
|
|
157
|
-
expect(paginationNode(queries[0] as QueryBuilder<Row>)).toMatchObject({ start: 0, end: 3 });
|
|
150
|
+
expect(window.nextCursor).toBeNull();
|
|
158
151
|
});
|
|
159
152
|
|
|
160
|
-
it('
|
|
161
|
-
const loader =
|
|
162
|
-
|
|
163
|
-
const window = await loader.loadWindow(
|
|
153
|
+
it('a full window with a NULL sort-value tail is exhausted (null rows collect at the tail; no anchor)', async () => {
|
|
154
|
+
const loader = loaderWithStubDb(sort);
|
|
155
|
+
staged.rows = [dated('a', '2026-08-10T12:00:00.000Z'), dated('b', '2026-08-09T12:00:00.000Z'), dated('c', null)];
|
|
156
|
+
const window = await loader.loadWindow(null, 3);
|
|
164
157
|
expect(window.nextCursor).toBeNull();
|
|
165
158
|
});
|
|
166
159
|
});
|