@teleporthq/teleport-plugin-next-data-source 0.43.75 → 0.44.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/__tests__/_helpers/first-page-runtime.ts +184 -0
- package/__tests__/_helpers/pagination-widget-fixture.ts +154 -5
- package/__tests__/booking-item-transform.test.ts +120 -0
- package/__tests__/browser-row-policy.test.ts +210 -4
- package/__tests__/data-source-request-locale.test.ts +4 -3
- package/__tests__/fetchers.test.ts +7 -3
- package/__tests__/fixed-list-sort.test.ts +1 -1
- package/__tests__/infinite-scroll.test.ts +363 -9
- package/__tests__/list-sort-order.test.ts +61 -0
- package/__tests__/null-filter-where.test.ts +132 -0
- package/__tests__/page-data-visitor-read.test.ts +196 -0
- package/__tests__/pg-date-parser.test.ts +73 -0
- package/__tests__/plain-list-sort.test.ts +2 -2
- package/__tests__/plain-list-starting-sort.test.ts +323 -0
- package/__tests__/product-price-sort.ts +11 -6
- package/__tests__/range-control.test.ts +159 -0
- package/__tests__/refetch-loading-state.test.ts +158 -2
- package/__tests__/search-input-marker.test.ts +86 -0
- package/__tests__/search-url-sync.test.ts +34 -8
- package/__tests__/starting-sort-first-page.test.ts +285 -0
- package/__tests__/table-read-route-protected-tables.test.ts +33 -3
- package/dist/cjs/cache/ast.d.ts +2 -0
- package/dist/cjs/cache/ast.d.ts.map +1 -1
- package/dist/cjs/cache/ast.js +5 -2
- package/dist/cjs/cache/ast.js.map +1 -1
- package/dist/cjs/count-effect.d.ts +7 -1
- package/dist/cjs/count-effect.d.ts.map +1 -1
- package/dist/cjs/count-effect.js +15 -5
- package/dist/cjs/count-effect.js.map +1 -1
- package/dist/cjs/data-source-fetchers.d.ts.map +1 -1
- package/dist/cjs/data-source-fetchers.js +10 -2
- package/dist/cjs/data-source-fetchers.js.map +1 -1
- package/dist/cjs/fetchers/pg-client-import.d.ts +12 -0
- package/dist/cjs/fetchers/pg-client-import.d.ts.map +1 -0
- package/dist/cjs/fetchers/pg-client-import.js +15 -0
- package/dist/cjs/fetchers/pg-client-import.js.map +1 -0
- package/dist/cjs/fetchers/postgresql.d.ts.map +1 -1
- package/dist/cjs/fetchers/postgresql.js +3 -1
- package/dist/cjs/fetchers/postgresql.js.map +1 -1
- package/dist/cjs/fetchers/raw-query.d.ts.map +1 -1
- package/dist/cjs/fetchers/raw-query.js +2 -1
- package/dist/cjs/fetchers/raw-query.js.map +1 -1
- package/dist/cjs/fetchers/teleport.d.ts.map +1 -1
- package/dist/cjs/fetchers/teleport.js +4 -2
- package/dist/cjs/fetchers/teleport.js.map +1 -1
- package/dist/cjs/fetchers/utils/browser-row-policy.d.ts.map +1 -1
- package/dist/cjs/fetchers/utils/browser-row-policy.js +5 -1
- package/dist/cjs/fetchers/utils/browser-row-policy.js.map +1 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +14 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/infinite-scroll.d.ts +89 -4
- package/dist/cjs/infinite-scroll.d.ts.map +1 -1
- package/dist/cjs/infinite-scroll.js +243 -33
- package/dist/cjs/infinite-scroll.js.map +1 -1
- package/dist/cjs/list-sort-order.d.ts +14 -0
- package/dist/cjs/list-sort-order.d.ts.map +1 -0
- package/dist/cjs/list-sort-order.js +36 -0
- package/dist/cjs/list-sort-order.js.map +1 -0
- package/dist/cjs/loading-state.d.ts +23 -2
- package/dist/cjs/loading-state.d.ts.map +1 -1
- package/dist/cjs/loading-state.js +50 -15
- package/dist/cjs/loading-state.js.map +1 -1
- package/dist/cjs/pagination-controls.d.ts +22 -3
- package/dist/cjs/pagination-controls.d.ts.map +1 -1
- package/dist/cjs/pagination-controls.js +29 -3
- package/dist/cjs/pagination-controls.js.map +1 -1
- package/dist/cjs/pagination-plugin.d.ts.map +1 -1
- package/dist/cjs/pagination-plugin.js +336 -164
- package/dist/cjs/pagination-plugin.js.map +1 -1
- package/dist/cjs/range-control.d.ts +45 -0
- package/dist/cjs/range-control.d.ts.map +1 -0
- package/dist/cjs/range-control.js +165 -0
- package/dist/cjs/range-control.js.map +1 -0
- package/dist/cjs/row-order.d.ts +3 -2
- package/dist/cjs/row-order.d.ts.map +1 -1
- package/dist/cjs/row-order.js +5 -4
- package/dist/cjs/row-order.js.map +1 -1
- package/dist/cjs/search-input.d.ts +42 -0
- package/dist/cjs/search-input.d.ts.map +1 -0
- package/dist/cjs/search-input.js +158 -0
- package/dist/cjs/search-input.js.map +1 -0
- package/dist/cjs/sort-utils.d.ts +53 -1
- package/dist/cjs/sort-utils.d.ts.map +1 -1
- package/dist/cjs/sort-utils.js +105 -13
- package/dist/cjs/sort-utils.js.map +1 -1
- package/dist/cjs/transformations/booking-item.d.ts +24 -0
- package/dist/cjs/transformations/booking-item.d.ts.map +1 -0
- package/dist/cjs/transformations/booking-item.js +27 -0
- package/dist/cjs/transformations/booking-item.js.map +1 -0
- package/dist/cjs/transformations/index.d.ts +4 -2
- package/dist/cjs/transformations/index.d.ts.map +1 -1
- package/dist/cjs/transformations/index.js +14 -5
- package/dist/cjs/transformations/index.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils.d.ts +3 -2
- package/dist/cjs/utils.d.ts.map +1 -1
- package/dist/cjs/utils.js +48 -18
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/cache/ast.d.ts +2 -0
- package/dist/esm/cache/ast.d.ts.map +1 -1
- package/dist/esm/cache/ast.js +3 -1
- package/dist/esm/cache/ast.js.map +1 -1
- package/dist/esm/count-effect.d.ts +7 -1
- package/dist/esm/count-effect.d.ts.map +1 -1
- package/dist/esm/count-effect.js +15 -5
- package/dist/esm/count-effect.js.map +1 -1
- package/dist/esm/data-source-fetchers.d.ts.map +1 -1
- package/dist/esm/data-source-fetchers.js +10 -2
- package/dist/esm/data-source-fetchers.js.map +1 -1
- package/dist/esm/fetchers/pg-client-import.d.ts +12 -0
- package/dist/esm/fetchers/pg-client-import.d.ts.map +1 -0
- package/dist/esm/fetchers/pg-client-import.js +12 -0
- package/dist/esm/fetchers/pg-client-import.js.map +1 -0
- package/dist/esm/fetchers/postgresql.d.ts.map +1 -1
- package/dist/esm/fetchers/postgresql.js +3 -1
- package/dist/esm/fetchers/postgresql.js.map +1 -1
- package/dist/esm/fetchers/raw-query.d.ts.map +1 -1
- package/dist/esm/fetchers/raw-query.js +2 -1
- package/dist/esm/fetchers/raw-query.js.map +1 -1
- package/dist/esm/fetchers/teleport.d.ts.map +1 -1
- package/dist/esm/fetchers/teleport.js +4 -2
- package/dist/esm/fetchers/teleport.js.map +1 -1
- package/dist/esm/fetchers/utils/browser-row-policy.d.ts.map +1 -1
- package/dist/esm/fetchers/utils/browser-row-policy.js +6 -2
- package/dist/esm/fetchers/utils/browser-row-policy.js.map +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +14 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/infinite-scroll.d.ts +89 -4
- package/dist/esm/infinite-scroll.d.ts.map +1 -1
- package/dist/esm/infinite-scroll.js +237 -32
- package/dist/esm/infinite-scroll.js.map +1 -1
- package/dist/esm/list-sort-order.d.ts +14 -0
- package/dist/esm/list-sort-order.d.ts.map +1 -0
- package/dist/esm/list-sort-order.js +32 -0
- package/dist/esm/list-sort-order.js.map +1 -0
- package/dist/esm/loading-state.d.ts +23 -2
- package/dist/esm/loading-state.d.ts.map +1 -1
- package/dist/esm/loading-state.js +50 -15
- package/dist/esm/loading-state.js.map +1 -1
- package/dist/esm/pagination-controls.d.ts +22 -3
- package/dist/esm/pagination-controls.d.ts.map +1 -1
- package/dist/esm/pagination-controls.js +28 -2
- package/dist/esm/pagination-controls.js.map +1 -1
- package/dist/esm/pagination-plugin.d.ts.map +1 -1
- package/dist/esm/pagination-plugin.js +340 -168
- package/dist/esm/pagination-plugin.js.map +1 -1
- package/dist/esm/range-control.d.ts +45 -0
- package/dist/esm/range-control.d.ts.map +1 -0
- package/dist/esm/range-control.js +137 -0
- package/dist/esm/range-control.js.map +1 -0
- package/dist/esm/row-order.d.ts +3 -2
- package/dist/esm/row-order.d.ts.map +1 -1
- package/dist/esm/row-order.js +5 -4
- package/dist/esm/row-order.js.map +1 -1
- package/dist/esm/search-input.d.ts +42 -0
- package/dist/esm/search-input.d.ts.map +1 -0
- package/dist/esm/search-input.js +129 -0
- package/dist/esm/search-input.js.map +1 -0
- package/dist/esm/sort-utils.d.ts +53 -1
- package/dist/esm/sort-utils.d.ts.map +1 -1
- package/dist/esm/sort-utils.js +100 -12
- package/dist/esm/sort-utils.js.map +1 -1
- package/dist/esm/transformations/booking-item.d.ts +24 -0
- package/dist/esm/transformations/booking-item.d.ts.map +1 -0
- package/dist/esm/transformations/booking-item.js +23 -0
- package/dist/esm/transformations/booking-item.js.map +1 -0
- package/dist/esm/transformations/index.d.ts +4 -2
- package/dist/esm/transformations/index.d.ts.map +1 -1
- package/dist/esm/transformations/index.js +14 -5
- package/dist/esm/transformations/index.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils.d.ts +3 -2
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/esm/utils.js +49 -19
- package/dist/esm/utils.js.map +1 -1
- package/package.json +5 -5
- package/src/cache/ast.ts +4 -1
- package/src/count-effect.ts +31 -8
- package/src/data-source-fetchers.ts +33 -14
- package/src/fetchers/pg-client-import.ts +16 -0
- package/src/fetchers/postgresql.ts +15 -9
- package/src/fetchers/raw-query.ts +2 -1
- package/src/fetchers/teleport.ts +19 -10
- package/src/fetchers/utils/browser-row-policy.ts +79 -5
- package/src/index.ts +8 -2
- package/src/infinite-scroll.ts +420 -81
- package/src/list-sort-order.ts +34 -0
- package/src/loading-state.ts +85 -13
- package/src/pagination-controls.ts +26 -3
- package/src/pagination-plugin.ts +532 -218
- package/src/range-control.ts +207 -0
- package/src/row-order.ts +5 -4
- package/src/search-input.ts +190 -0
- package/src/sort-utils.ts +164 -21
- package/src/transformations/booking-item.ts +71 -0
- package/src/transformations/index.ts +25 -2
- package/src/utils.ts +55 -18
|
@@ -47,22 +47,24 @@ import { ChunkType, FileType, } from '@teleporthq/teleport-types';
|
|
|
47
47
|
import * as types from '@babel/types';
|
|
48
48
|
import { parseExpression } from '@babel/parser';
|
|
49
49
|
import { ASTStatementOrder, GenericUtils, StringUtils } from '@teleporthq/teleport-shared';
|
|
50
|
-
import { ASTUtils, URLQueryWriter, URLSearchParamSync } from '@teleporthq/teleport-plugin-common';
|
|
50
|
+
import { ASTUtils, RouteUtils, URLQueryWriter, URLSearchParamSync, } from '@teleporthq/teleport-plugin-common';
|
|
51
51
|
import { collectFilterLeafConditions, generateSafeFileName, pruneFilterTree } from './utils';
|
|
52
52
|
import { generateDataSourceFetcherWithCore } from './data-source-fetchers';
|
|
53
53
|
import { buildProductTransformOptions } from './transformations';
|
|
54
|
-
import { appendSortsParam,
|
|
54
|
+
import { appendSortsParam, buildSortAtStartGuard, buildStartingSortsValue, readRepeaterSort, } from './sort-utils';
|
|
55
55
|
import { appendFiltersParam, buildStaticFiltersStringifyCall, pushStateIdsAsDeps, pushPropIdsAsDeps, } from './filter-utils';
|
|
56
56
|
import { appendItemsPathParam, extractItemsPath } from './items-path';
|
|
57
57
|
import { resolveRepeaterPerPage } from './repeater-page-size';
|
|
58
58
|
import { applyLoadingStateToDataProvider, buildLoadingStateDeclarations, getLoadingStateVars, } from './loading-state';
|
|
59
59
|
import { mergeServerCacheOptions, resolveCacheFromRepeaterContent } from './cache/config';
|
|
60
|
-
import { buildCacheHydrationEffect, buildCacheStoreThen, buildCachedFetchBody, buildCachedParamsDeclarations, registerCacheClientImports, } from './cache/ast';
|
|
61
|
-
import { convertControlToButton, dropInactivePaginationControls, findPaginationControl, setJSXExpressionAttribute, } from './pagination-controls';
|
|
60
|
+
import { buildCacheHydrationEffect, buildCacheStoreThen, buildCachedFetchBody, buildCachedParamsDeclarations, paramsVarFor, registerCacheClientImports, } from './cache/ast';
|
|
61
|
+
import { convertControlToButton, dropInactivePaginationControls, findAllPaginationControls, findPaginationControl, PAGINATION_FOR_ATTR, readJSXAttributeString, setJSXExpressionAttribute, } from './pagination-controls';
|
|
62
|
+
import { findRangeControls, wireRangeControl } from './range-control';
|
|
63
|
+
import { findAllSearchInputsInJSX, pairSearchInputs, wireSearchInput } from './search-input';
|
|
62
64
|
import { buildCountFetchEffect, buildCountSeqDeclaration } from './count-effect';
|
|
63
65
|
import { findAllSearchClearButtonsInJSX, findSiblingSearchInput, wireSearchClearButton, } from './search-clear';
|
|
64
66
|
import { buildPageTokensDeclaration, wireNumberedPagination, } from './numbered-pagination';
|
|
65
|
-
import { buildAccumulatingResponseHandler, buildInfiniteScrollDeclarations, buildSentinelElement, buildSentinelObserverEffect, getInfiniteScrollVars, } from './infinite-scroll';
|
|
67
|
+
import { buildAccumulatingRequestMark, buildAccumulatingResponseHandler, buildAppendingRequestCheck, buildFirstPageDeclaration, buildFirstPageSeedEffect, buildInfiniteScrollDeclarations, buildSentinelElement, buildSentinelObserverEffect, buildServerRowsExpression, getInfiniteScrollVars, } from './infinite-scroll';
|
|
66
68
|
import { buildFilterSortPageResetEffect, buildPageResetRefDeclaration, hasNoPageResetDeps, } from './page-reset';
|
|
67
69
|
import { buildPageUrlRefDeclaration, buildPageUrlSyncEffect } from './page-url-sync';
|
|
68
70
|
import { isLocalizedProject } from './content-localization';
|
|
@@ -273,7 +275,7 @@ function buildFilterDestinationExpression(destination) {
|
|
|
273
275
|
return ASTUtils.convertFilterDestinationToExpression(destination);
|
|
274
276
|
}
|
|
275
277
|
// Scan UIDL to find all data source usages and build a registry
|
|
276
|
-
function buildStateRegistry(uidlNode) {
|
|
278
|
+
function buildStateRegistry(uidlNode, stateDefinitions) {
|
|
277
279
|
var usages = [];
|
|
278
280
|
var byDataSourceId = new Map();
|
|
279
281
|
var byArrayMapperRenderProp = new Map();
|
|
@@ -330,16 +332,19 @@ function buildStateRegistry(uidlNode) {
|
|
|
330
332
|
// is skipped for a dynamic sort) — the pre-rendered HTML carried no
|
|
331
333
|
// posts, and the browser fetched page 1 a second time. Only a sort
|
|
332
334
|
// bound to state (the admin panel's sortable columns) is dynamic.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
335
|
+
//
|
|
336
|
+
// A sort the visitor picks still starts somewhere — the store's sort
|
|
337
|
+
// dropdown at "Name A-Z". Known at build time, it orders the
|
|
338
|
+
// server-side first page, which the list then shows while the visitor
|
|
339
|
+
// leaves the sort alone. Read as a plain list's page fetch reads it.
|
|
340
|
+
var repeaterSort = !sorts || sorts.length === 0
|
|
341
|
+
? readRepeaterSort(content.sort, content.sortDirection, stateDefinitions)
|
|
342
|
+
: {};
|
|
343
|
+
if (repeaterSort.fixed) {
|
|
344
|
+
sorts = [repeaterSort.fixed];
|
|
342
345
|
}
|
|
346
|
+
var dynamicSort = repeaterSort.dynamic;
|
|
347
|
+
var startingSort = repeaterSort.starting;
|
|
343
348
|
// Extract filters from parent's resource params, keeping the group tree
|
|
344
349
|
// the inspector authored (see `readFilterTree`).
|
|
345
350
|
var filters = [];
|
|
@@ -407,6 +412,7 @@ function buildStateRegistry(uidlNode) {
|
|
|
407
412
|
index: index++,
|
|
408
413
|
dataSourceIdentifier: parentDataSource.identifier,
|
|
409
414
|
arrayMapperRenderProp: arrayMapperRenderProp,
|
|
415
|
+
nodeId: typeof content.nodeId === 'string' ? content.nodeId : undefined,
|
|
410
416
|
resourceDefinition: {
|
|
411
417
|
dataSourceId: parentDataSource.resourceDef.dataSourceId || '',
|
|
412
418
|
tableName: parentDataSource.resourceDef.tableName || '',
|
|
@@ -421,6 +427,7 @@ function buildStateRegistry(uidlNode) {
|
|
|
421
427
|
queryColumns: queryColumns,
|
|
422
428
|
sorts: sorts,
|
|
423
429
|
dynamicSort: dynamicSort,
|
|
430
|
+
startingSort: startingSort,
|
|
424
431
|
filters: filters,
|
|
425
432
|
filterStateIds: filterStateIds,
|
|
426
433
|
filterPropIds: filterPropIds,
|
|
@@ -502,6 +509,8 @@ function getStateVarsForUsage(usage) {
|
|
|
502
509
|
setPageStateVar: "setDs_".concat(idx, "_page"),
|
|
503
510
|
maxPagesStateVar: "ds_".concat(idx, "_maxPages"),
|
|
504
511
|
setMaxPagesStateVar: "setDs_".concat(idx, "_maxPages"),
|
|
512
|
+
totalStateVar: "ds_".concat(idx, "_total"),
|
|
513
|
+
setTotalStateVar: "setDs_".concat(idx, "_total"),
|
|
505
514
|
searchQueryVar: "ds_".concat(idx, "_searchQuery"),
|
|
506
515
|
setSearchQueryVar: "setDs_".concat(idx, "_searchQuery"),
|
|
507
516
|
debouncedSearchQueryVar: "ds_".concat(idx, "_debouncedQuery"),
|
|
@@ -579,19 +588,27 @@ function pushSearchUrlSyncEffects(effectStatements, usage, vars) {
|
|
|
579
588
|
effectStatements.push(URLSearchParamSync.buildUrlWriteBackEffect(usage.searchUrlParamKey, buildDebouncedValueExpr(), buildDebouncedValueExpr(), undefined, adoptedRefVar));
|
|
580
589
|
// read-back: `?<searchUrlParamKey>=` → the input AND the applied query at once
|
|
581
590
|
// (`ds_N_adoptUrlSearch`), so an address is not a typed change: it skips the
|
|
582
|
-
// debounce and keeps
|
|
591
|
+
// debounce and keeps a page the address carries — `?searchKeyword=x&page=3`
|
|
592
|
+
// lands on page 3.
|
|
583
593
|
effectStatements.push(URLSearchParamSync.buildUrlReadBackEffect(usage.searchUrlParamKey, adopterVar, undefined, adoptedRefVar));
|
|
584
594
|
}
|
|
585
595
|
// `const ds_N_adoptUrlSearch = (update) => { … }`: the setter the search's URL
|
|
586
596
|
// read-back calls with its `(prev) => next` updater. It moves the input and the
|
|
587
|
-
// applied (debounced) query together
|
|
588
|
-
// page
|
|
597
|
+
// applied (debounced) query together. A list whose page is in the address
|
|
598
|
+
// keeps its page — the page sync sets it from the same address. Any other
|
|
599
|
+
// list starts the new query on page 1, as a typed change does in the debounce
|
|
600
|
+
// effect: an appending list has usually advanced past page 1 by the time the
|
|
601
|
+
// router is ready, and the query's first answer would otherwise be its page 2
|
|
602
|
+
// — empty for a query only a few rows match.
|
|
589
603
|
function buildUrlSearchAdopter(adopterVar, usage, vars) {
|
|
590
604
|
var update = types.identifier('update');
|
|
605
|
+
var pageReset = usageHasPageUrlSync(usage)
|
|
606
|
+
? []
|
|
607
|
+
: [types.objectProperty(types.identifier('page'), types.numericLiteral(1))];
|
|
591
608
|
var applyToDebounced = usage.category === 'paginated+search'
|
|
592
609
|
? // setDs_N_state((state) => {
|
|
593
610
|
// const next = update(state.debouncedQuery)
|
|
594
|
-
// return next === state.debouncedQuery ? state : { ...state, debouncedQuery: next }
|
|
611
|
+
// return next === state.debouncedQuery ? state : { ...state, page: 1, debouncedQuery: next }
|
|
595
612
|
// })
|
|
596
613
|
types.callExpression(types.identifier(vars.setCombinedStateVar), [
|
|
597
614
|
types.arrowFunctionExpression([types.identifier('state')], types.blockStatement([
|
|
@@ -600,10 +617,11 @@ function buildUrlSearchAdopter(adopterVar, usage, vars) {
|
|
|
600
617
|
types.memberExpression(types.identifier('state'), types.identifier('debouncedQuery')),
|
|
601
618
|
])),
|
|
602
619
|
]),
|
|
603
|
-
types.returnStatement(types.conditionalExpression(types.binaryExpression('===', types.identifier('next'), types.memberExpression(types.identifier('state'), types.identifier('debouncedQuery'))), types.identifier('state'), types.objectExpression([
|
|
604
|
-
types.spreadElement(types.identifier('state'))
|
|
620
|
+
types.returnStatement(types.conditionalExpression(types.binaryExpression('===', types.identifier('next'), types.memberExpression(types.identifier('state'), types.identifier('debouncedQuery'))), types.identifier('state'), types.objectExpression(__spreadArray(__spreadArray([
|
|
621
|
+
types.spreadElement(types.identifier('state'))
|
|
622
|
+
], pageReset, true), [
|
|
605
623
|
types.objectProperty(types.identifier('debouncedQuery'), types.identifier('next')),
|
|
606
|
-
]))),
|
|
624
|
+
], false)))),
|
|
607
625
|
])),
|
|
608
626
|
])
|
|
609
627
|
: types.callExpression(types.identifier(vars.setDebouncedSearchQueryVar), [update]);
|
|
@@ -766,7 +784,7 @@ function pushFilterSortPageResetEffect(stateDeclarations, effectStatements, usag
|
|
|
766
784
|
// ==================== MAIN PLUGIN ====================
|
|
767
785
|
export var createNextArrayMapperPaginationPlugin = function () {
|
|
768
786
|
var paginationPlugin = function (structure) { return __awaiter(void 0, void 0, void 0, function () {
|
|
769
|
-
var uidl, chunks, dependencies, options, componentChunk, variableDeclaration, declarator, arrowFunction, blockStatement, registry, getStaticPropsChunk, isPage, localized, stateDeclarations, effectStatements, needsUseRouter, returnIndex, insertIndex, dataProviders, dataProvidersWithRepeaters, usageIndexByDataSourceId, loadingStateDeclarations, usagesWithLoadingState, usageByProviderNode, cacheDeclarations, sharedOptions, cachedScopes, dataProvidersWithoutRepeaters, searchInputs,
|
|
787
|
+
var uidl, chunks, dependencies, options, componentChunk, variableDeclaration, declarator, arrowFunction, blockStatement, rangeControls, hasRangeControl, registry, getStaticPropsChunk, isPage, localized, stateDeclarations, effectStatements, needsUseRouter, returnIndex, insertIndex, dataProviders, dataProvidersWithRepeaters, usageIndexByDataSourceId, loadingStateDeclarations, usagesWithLoadingState, usageByProviderNode, cacheDeclarations, firstPageDeclarations, sharedOptions, cachedScopes, dataProvidersWithoutRepeaters, searchInputs, usageBySearchInput, _i, searchInputs_1, input, usage;
|
|
770
788
|
var _a, _b;
|
|
771
789
|
return __generator(this, function (_c) {
|
|
772
790
|
uidl = structure.uidl, chunks = structure.chunks, dependencies = structure.dependencies, options = structure.options;
|
|
@@ -790,7 +808,9 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
790
808
|
return [2 /*return*/, structure];
|
|
791
809
|
}
|
|
792
810
|
blockStatement = arrowFunction.body;
|
|
793
|
-
|
|
811
|
+
rangeControls = findRangeControls(blockStatement);
|
|
812
|
+
hasRangeControl = rangeControls.length > 0;
|
|
813
|
+
registry = buildStateRegistry(uidl.node, uidl.stateDefinitions);
|
|
794
814
|
if (registry.usages.length === 0) {
|
|
795
815
|
return [2 /*return*/, structure];
|
|
796
816
|
}
|
|
@@ -958,11 +978,15 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
958
978
|
pushPropIdsAsDeps(countEffectDeps, countEffectSeen, usage.filterPropIds);
|
|
959
979
|
// Same goes for URL-driven filters (already documented above).
|
|
960
980
|
pushUrlSearchParamMemoDeps(countEffectDeps, usage);
|
|
981
|
+
if (hasRangeControl) {
|
|
982
|
+
stateDeclarations.push(buildTotalDeclaration(vars));
|
|
983
|
+
}
|
|
961
984
|
stateDeclarations.push(buildCountSeqDeclaration(vars.countSeqRefVar));
|
|
962
985
|
effectStatements.push(buildCountFetchEffect({
|
|
963
986
|
fileName: fileName,
|
|
964
987
|
perPage: usage.perPage,
|
|
965
988
|
setMaxPagesVar: vars.setMaxPagesStateVar,
|
|
989
|
+
setTotalVar: hasRangeControl ? vars.setTotalStateVar : undefined,
|
|
966
990
|
urlParams: urlParams,
|
|
967
991
|
deps: countEffectDeps,
|
|
968
992
|
countSeqRefVar: vars.countSeqRefVar,
|
|
@@ -1004,7 +1028,9 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
1004
1028
|
// "Next" button, but not to label a numbered strip or to know when an
|
|
1005
1029
|
// infinite list has reached its end, so those two modes fetch a live
|
|
1006
1030
|
// count as well.
|
|
1007
|
-
|
|
1031
|
+
// A range text needs the live count too: the build-time count only
|
|
1032
|
+
// ever became a page count, never the total it shows.
|
|
1033
|
+
var needsLiveCount = !isPage || usage.paginationMode === 'numbered' || usage.infiniteScroll || hasRangeControl;
|
|
1008
1034
|
if (needsLiveCount) {
|
|
1009
1035
|
var fileName = generateSafeFileName(usage.resourceDefinition.dataSourceType, usage.resourceDefinition.tableName, usage.resourceDefinition.dataSourceId);
|
|
1010
1036
|
// ⛔ This list has no search input, so no `query` param — but it may
|
|
@@ -1026,11 +1052,15 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
1026
1052
|
pushStateIdsAsDeps(countDeps, countDepsSeen, usage.filterStateIds);
|
|
1027
1053
|
pushPropIdsAsDeps(countDeps, countDepsSeen, usage.filterPropIds);
|
|
1028
1054
|
pushUrlSearchParamMemoDeps(countDeps, usage);
|
|
1055
|
+
if (hasRangeControl) {
|
|
1056
|
+
stateDeclarations.push(buildTotalDeclaration(vars));
|
|
1057
|
+
}
|
|
1029
1058
|
stateDeclarations.push(buildCountSeqDeclaration(vars.countSeqRefVar));
|
|
1030
1059
|
effectStatements.push(buildCountFetchEffect({
|
|
1031
1060
|
fileName: fileName,
|
|
1032
1061
|
perPage: usage.perPage,
|
|
1033
1062
|
setMaxPagesVar: vars.setMaxPagesStateVar,
|
|
1063
|
+
setTotalVar: hasRangeControl ? vars.setTotalStateVar : undefined,
|
|
1034
1064
|
urlParams: countUrlParams,
|
|
1035
1065
|
deps: countDeps,
|
|
1036
1066
|
countSeqRefVar: vars.countSeqRefVar,
|
|
@@ -1115,6 +1145,7 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
1115
1145
|
usagesWithLoadingState = new Set();
|
|
1116
1146
|
usageByProviderNode = new Map();
|
|
1117
1147
|
cacheDeclarations = [];
|
|
1148
|
+
firstPageDeclarations = isPage ? [] : undefined;
|
|
1118
1149
|
dataProvidersWithRepeaters.forEach(function (dp) {
|
|
1119
1150
|
var _a, _b;
|
|
1120
1151
|
var nameAttr = dp.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'name'; });
|
|
@@ -1135,10 +1166,10 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
1135
1166
|
var fileName = generateSafeFileName(usage.resourceDefinition.dataSourceType, usage.resourceDefinition.tableName, usage.resourceDefinition.dataSourceId);
|
|
1136
1167
|
// Update DataProvider based on category
|
|
1137
1168
|
if (usage.category === 'paginated+search') {
|
|
1138
|
-
updateDataProviderForPaginatedSearch(dp, usage, vars, fileName, cacheDeclarations, localized);
|
|
1169
|
+
updateDataProviderForPaginatedSearch(dp, usage, vars, fileName, cacheDeclarations, localized, firstPageDeclarations);
|
|
1139
1170
|
}
|
|
1140
1171
|
else if (usage.category === 'paginated-only') {
|
|
1141
|
-
updateDataProviderForPaginationOnly(dp, usage, vars, fileName, cacheDeclarations, localized);
|
|
1172
|
+
updateDataProviderForPaginationOnly(dp, usage, vars, fileName, cacheDeclarations, localized, firstPageDeclarations);
|
|
1142
1173
|
}
|
|
1143
1174
|
else if (usage.category === 'search-only') {
|
|
1144
1175
|
updateDataProviderForSearchOnly(dp, usage, vars, fileName, cacheDeclarations, localized);
|
|
@@ -1150,9 +1181,14 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
1150
1181
|
// change refetches, instead of leaving the previous rows on screen with
|
|
1151
1182
|
// no feedback. Runs last so it sees the `fetchData` and
|
|
1152
1183
|
// `persistDataDuringLoading` attributes the updaters above just wrote.
|
|
1184
|
+
// An appending list keeps its rows on screen while its next page loads;
|
|
1185
|
+
// only a list loading afresh falls through to the loading slot.
|
|
1153
1186
|
var loadingVars = getLoadingStateVars(usage.index);
|
|
1154
|
-
|
|
1155
|
-
|
|
1187
|
+
var appendingRequest = usage.infiniteScroll && usage.paginated
|
|
1188
|
+
? buildAppendingRequestCheck(getInfiniteScrollVars(usage.index))
|
|
1189
|
+
: undefined;
|
|
1190
|
+
if (applyLoadingStateToDataProvider(dp, loadingVars, appendingRequest)) {
|
|
1191
|
+
loadingStateDeclarations.push.apply(loadingStateDeclarations, buildLoadingStateDeclarations(loadingVars, !!appendingRequest));
|
|
1156
1192
|
// Recorded because the loading state is only declared for a provider
|
|
1157
1193
|
// that HAS a loading slot; a Load More button wired later may only
|
|
1158
1194
|
// reference `ds_N_isFetching` if it actually exists.
|
|
@@ -1161,7 +1197,9 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
1161
1197
|
// An auto-loading list needs something at the end of the rows for its
|
|
1162
1198
|
// IntersectionObserver to watch.
|
|
1163
1199
|
if (usage.infiniteScroll && usage.paginated && !usage.infiniteScrollLoadMore) {
|
|
1164
|
-
insertSentinelAfterProvider(blockStatement, dp,
|
|
1200
|
+
insertSentinelAfterProvider(blockStatement, dp, function (parentTag) {
|
|
1201
|
+
return buildSentinelElement(getInfiniteScrollVars(usage.index), parentTag);
|
|
1202
|
+
});
|
|
1165
1203
|
}
|
|
1166
1204
|
// Create API route for all categories (including 'plain' for components)
|
|
1167
1205
|
ensureAPIRouteExists(options.extractedResources, usage, options.dataSources, buildProductTransformOptions(options));
|
|
@@ -1195,6 +1233,11 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
1195
1233
|
ASTStatementOrder.insertStatementsAfterDependencies(blockStatement, cacheDeclarations);
|
|
1196
1234
|
registerCacheClientImports(dependencies, (_a = uidl.outputOptions) === null || _a === void 0 ? void 0 : _a.folderPath);
|
|
1197
1235
|
}
|
|
1236
|
+
// After the cache declarations: a cached list's first page reads the
|
|
1237
|
+
// `ds_N_params` they hoisted.
|
|
1238
|
+
if (firstPageDeclarations === null || firstPageDeclarations === void 0 ? void 0 : firstPageDeclarations.length) {
|
|
1239
|
+
ASTStatementOrder.insertStatementsAfterDependencies(blockStatement, firstPageDeclarations);
|
|
1240
|
+
}
|
|
1198
1241
|
dataProvidersWithoutRepeaters = dataProviders.filter(function (dp) {
|
|
1199
1242
|
var hasRepeater = findArrayMapperRenderPropInDataProvider(dp) !== undefined;
|
|
1200
1243
|
return !hasRepeater;
|
|
@@ -1203,17 +1246,14 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
1203
1246
|
stabilizeDataProviderWithoutRepeater(dp);
|
|
1204
1247
|
});
|
|
1205
1248
|
searchInputs = findAllSearchInputsInJSX(blockStatement);
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1249
|
+
usageBySearchInput = pairSearchInputs(searchInputs, registry.usages);
|
|
1250
|
+
for (_i = 0, searchInputs_1 = searchInputs; _i < searchInputs_1.length; _i++) {
|
|
1251
|
+
input = searchInputs_1[_i];
|
|
1252
|
+
usage = usageBySearchInput.get(input.node);
|
|
1253
|
+
if (usage) {
|
|
1254
|
+
wireSearchInput(input, getStateVarsForUsage(usage));
|
|
1211
1255
|
}
|
|
1212
|
-
|
|
1213
|
-
var vars = getStateVarsForUsage(usage);
|
|
1214
|
-
wireSearchInput(input.node, vars);
|
|
1215
|
-
usageBySearchInput.set(input.node, usage);
|
|
1216
|
-
});
|
|
1256
|
+
}
|
|
1217
1257
|
// STEP 4.5: Wire the clear buttons, each to the input it shares a parent with.
|
|
1218
1258
|
findAllSearchClearButtonsInJSX(blockStatement).forEach(function (button) {
|
|
1219
1259
|
var input = findSiblingSearchInput(button, searchInputs.map(function (entry) { return entry.node; }));
|
|
@@ -1240,9 +1280,29 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
1240
1280
|
}
|
|
1241
1281
|
wirePaginationWidget(node, usage, getStateVarsForUsage(usage), usagesWithLoadingState.has(usage.index));
|
|
1242
1282
|
});
|
|
1243
|
-
// STEP
|
|
1283
|
+
// STEP 5b: Wire the range texts that name their mapper.
|
|
1284
|
+
//
|
|
1285
|
+
// A `range` control carrying `data-tq-pagination-for` belongs to the mapper
|
|
1286
|
+
// whose editor node id it names, wherever it sits — a template's footer or
|
|
1287
|
+
// toolbar is laid out by the author, not inside a pagination container, so
|
|
1288
|
+
// the container-ownership rule above cannot reach it. One without the
|
|
1289
|
+
// attribute was wired by its container in STEP 5; one naming a mapper this
|
|
1290
|
+
// component does not render stays as drawn.
|
|
1291
|
+
rangeControls.forEach(function (control) {
|
|
1292
|
+
var ownerNodeId = readJSXAttributeString(control, PAGINATION_FOR_ATTR);
|
|
1293
|
+
if (!ownerNodeId) {
|
|
1294
|
+
return;
|
|
1295
|
+
}
|
|
1296
|
+
var owner = registry.usages.find(function (usage) { return usage.nodeId === ownerNodeId; });
|
|
1297
|
+
if (owner) {
|
|
1298
|
+
wireRangeControlFor(control, owner, getStateVarsForUsage(owner));
|
|
1299
|
+
}
|
|
1300
|
+
});
|
|
1301
|
+
// STEP 6: Update getStaticProps if this is a page. Its rows are what the
|
|
1302
|
+
// page renders, so they are read as a visitor is served them — unless only
|
|
1303
|
+
// the store's trusted readers can open the page (`pageDataReadArguments`).
|
|
1244
1304
|
if (isPage) {
|
|
1245
|
-
updateGetStaticProps(chunks, registry, dependencies, (_b = uidl.outputOptions) === null || _b === void 0 ? void 0 : _b.folderPath, localized);
|
|
1305
|
+
updateGetStaticProps(chunks, registry, dependencies, (_b = uidl.outputOptions) === null || _b === void 0 ? void 0 : _b.folderPath, localized, function () { return RouteUtils.pageDataReadArguments(uidl, options.auth); });
|
|
1246
1306
|
}
|
|
1247
1307
|
return [2 /*return*/, structure];
|
|
1248
1308
|
});
|
|
@@ -1257,39 +1317,59 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
1257
1317
|
* It has to be a sibling: the provider's own child is a render-prop function,
|
|
1258
1318
|
* and anything placed inside it would be re-created on every fetch — the
|
|
1259
1319
|
* observer would then be watching an element that is no longer in the document.
|
|
1320
|
+
* The sentinel is built for the element it lands in (`buildSentinelElement`):
|
|
1321
|
+
* a fragment is transparent, a component's children may go anywhere.
|
|
1260
1322
|
*
|
|
1261
1323
|
* Returns false when the provider has no element parent to splice into (a
|
|
1262
1324
|
* provider returned directly from the component), leaving the list on its
|
|
1263
1325
|
* count-driven `hasMore` rather than injecting a stray node.
|
|
1264
1326
|
*/
|
|
1265
|
-
function insertSentinelAfterProvider(blockStatement, provider,
|
|
1327
|
+
function insertSentinelAfterProvider(blockStatement, provider, buildSentinel) {
|
|
1266
1328
|
var inserted = false;
|
|
1267
|
-
var
|
|
1329
|
+
var elementTagOf = function (node, enclosing) {
|
|
1330
|
+
var _a;
|
|
1331
|
+
if ((node === null || node === void 0 ? void 0 : node.type) === 'JSXFragment') {
|
|
1332
|
+
return enclosing;
|
|
1333
|
+
}
|
|
1334
|
+
if ((node === null || node === void 0 ? void 0 : node.type) !== 'JSXElement') {
|
|
1335
|
+
return enclosing;
|
|
1336
|
+
}
|
|
1337
|
+
var name = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.name;
|
|
1338
|
+
if ((name === null || name === void 0 ? void 0 : name.type) !== 'JSXIdentifier') {
|
|
1339
|
+
return null;
|
|
1340
|
+
}
|
|
1341
|
+
if (name.name === 'Fragment') {
|
|
1342
|
+
return enclosing;
|
|
1343
|
+
}
|
|
1344
|
+
return /^[a-z]/.test(name.name) ? name.name : null;
|
|
1345
|
+
};
|
|
1346
|
+
var traverse = function (node, enclosing) {
|
|
1268
1347
|
if (!node || inserted) {
|
|
1269
1348
|
return;
|
|
1270
1349
|
}
|
|
1350
|
+
var tag = elementTagOf(node, enclosing);
|
|
1271
1351
|
if (Array.isArray(node.children)) {
|
|
1272
1352
|
var at = node.children.indexOf(provider);
|
|
1273
1353
|
if (at !== -1) {
|
|
1274
|
-
node.children.splice(at + 1, 0,
|
|
1354
|
+
node.children.splice(at + 1, 0, buildSentinel(tag));
|
|
1275
1355
|
inserted = true;
|
|
1276
1356
|
return;
|
|
1277
1357
|
}
|
|
1278
|
-
node.children.forEach(traverse);
|
|
1358
|
+
node.children.forEach(function (child) { return traverse(child, tag); });
|
|
1279
1359
|
}
|
|
1280
1360
|
if (node.body) {
|
|
1281
1361
|
if (Array.isArray(node.body)) {
|
|
1282
|
-
node.body.forEach(traverse);
|
|
1362
|
+
node.body.forEach(function (child) { return traverse(child, tag); });
|
|
1283
1363
|
}
|
|
1284
1364
|
else {
|
|
1285
|
-
traverse(node.body);
|
|
1365
|
+
traverse(node.body, tag);
|
|
1286
1366
|
}
|
|
1287
1367
|
}
|
|
1288
1368
|
if (node.consequent) {
|
|
1289
|
-
traverse(node.consequent);
|
|
1369
|
+
traverse(node.consequent, tag);
|
|
1290
1370
|
}
|
|
1291
1371
|
if (node.alternate) {
|
|
1292
|
-
traverse(node.alternate);
|
|
1372
|
+
traverse(node.alternate, tag);
|
|
1293
1373
|
}
|
|
1294
1374
|
// `{activeTabIndex === 0 && (<div>…<DataProvider/>…</div>)}` — a tab
|
|
1295
1375
|
// panel, a gated section: the provider sits on the RIGHT of a logical
|
|
@@ -1297,22 +1377,22 @@ function insertSentinelAfterProvider(blockStatement, provider, sentinel) {
|
|
|
1297
1377
|
// an argument. Left unvisited, the products list under the first tab of
|
|
1298
1378
|
// a shop was never paginated or seeded, and rendered nothing.
|
|
1299
1379
|
if (node.left) {
|
|
1300
|
-
traverse(node.left);
|
|
1380
|
+
traverse(node.left, tag);
|
|
1301
1381
|
}
|
|
1302
1382
|
if (node.right) {
|
|
1303
|
-
traverse(node.right);
|
|
1383
|
+
traverse(node.right, tag);
|
|
1304
1384
|
}
|
|
1305
1385
|
if (node.test) {
|
|
1306
|
-
traverse(node.test);
|
|
1386
|
+
traverse(node.test, tag);
|
|
1307
1387
|
}
|
|
1308
1388
|
if (node.expression) {
|
|
1309
|
-
traverse(node.expression);
|
|
1389
|
+
traverse(node.expression, tag);
|
|
1310
1390
|
}
|
|
1311
1391
|
if (node.argument) {
|
|
1312
|
-
traverse(node.argument);
|
|
1392
|
+
traverse(node.argument, tag);
|
|
1313
1393
|
}
|
|
1314
1394
|
};
|
|
1315
|
-
traverse(blockStatement);
|
|
1395
|
+
traverse(blockStatement, null);
|
|
1316
1396
|
return inserted;
|
|
1317
1397
|
}
|
|
1318
1398
|
function findAllDataProvidersInJSX(blockStatement) {
|
|
@@ -1407,61 +1487,6 @@ function findArrayMapperRenderPropInDataProvider(dataProvider) {
|
|
|
1407
1487
|
}
|
|
1408
1488
|
return renderItemAttr.value.expression.params[0].name;
|
|
1409
1489
|
}
|
|
1410
|
-
function findAllSearchInputsInJSX(blockStatement) {
|
|
1411
|
-
var results = [];
|
|
1412
|
-
var traverse = function (node) {
|
|
1413
|
-
var _a, _b, _c, _d, _e, _f;
|
|
1414
|
-
if (!node) {
|
|
1415
|
-
return;
|
|
1416
|
-
}
|
|
1417
|
-
if (node.type === 'JSXElement' && ((_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.name) === 'input') {
|
|
1418
|
-
var classAttr = (_c = node.openingElement.attributes) === null || _c === void 0 ? void 0 : _c.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'className'; });
|
|
1419
|
-
var className = ((_d = classAttr === null || classAttr === void 0 ? void 0 : classAttr.value) === null || _d === void 0 ? void 0 : _d.value) || ((_f = (_e = classAttr === null || classAttr === void 0 ? void 0 : classAttr.value) === null || _e === void 0 ? void 0 : _e.expression) === null || _f === void 0 ? void 0 : _f.value) || '';
|
|
1420
|
-
if (className.includes('search-input')) {
|
|
1421
|
-
results.push({ node: node, className: className });
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
|
-
if (node.children && Array.isArray(node.children)) {
|
|
1425
|
-
node.children.forEach(function (c) { return traverse(c); });
|
|
1426
|
-
}
|
|
1427
|
-
if (node.body) {
|
|
1428
|
-
if (Array.isArray(node.body)) {
|
|
1429
|
-
node.body.forEach(function (s) { return traverse(s); });
|
|
1430
|
-
}
|
|
1431
|
-
else {
|
|
1432
|
-
traverse(node.body);
|
|
1433
|
-
}
|
|
1434
|
-
}
|
|
1435
|
-
if (node.consequent) {
|
|
1436
|
-
traverse(node.consequent);
|
|
1437
|
-
}
|
|
1438
|
-
if (node.alternate) {
|
|
1439
|
-
traverse(node.alternate);
|
|
1440
|
-
}
|
|
1441
|
-
// `{activeTabIndex === 0 && (<div>…<DataProvider/>…</div>)}` — a tab
|
|
1442
|
-
// panel, a gated section: the provider sits on the RIGHT of a logical
|
|
1443
|
-
// expression (or in a ternary's `test`), which is not a child, a body or
|
|
1444
|
-
// an argument. Left unvisited, the products list under the first tab of
|
|
1445
|
-
// a shop was never paginated or seeded, and rendered nothing.
|
|
1446
|
-
if (node.left) {
|
|
1447
|
-
traverse(node.left);
|
|
1448
|
-
}
|
|
1449
|
-
if (node.right) {
|
|
1450
|
-
traverse(node.right);
|
|
1451
|
-
}
|
|
1452
|
-
if (node.test) {
|
|
1453
|
-
traverse(node.test);
|
|
1454
|
-
}
|
|
1455
|
-
if (node.expression) {
|
|
1456
|
-
traverse(node.expression);
|
|
1457
|
-
}
|
|
1458
|
-
if (node.argument) {
|
|
1459
|
-
traverse(node.argument);
|
|
1460
|
-
}
|
|
1461
|
-
};
|
|
1462
|
-
traverse(blockStatement);
|
|
1463
|
-
return results;
|
|
1464
|
-
}
|
|
1465
1490
|
/**
|
|
1466
1491
|
* Every pagination widget in the JSX, paired with the mapper it belongs to.
|
|
1467
1492
|
*
|
|
@@ -1536,34 +1561,97 @@ function findPaginationNodesWithOwners(blockStatement, usageByProviderNode) {
|
|
|
1536
1561
|
*
|
|
1537
1562
|
* An uncached mapper keeps the inline `params={useMemo(...)}` it has always had,
|
|
1538
1563
|
* byte for byte. A cached one hoists that memo into a component const so the
|
|
1539
|
-
* peek can depend on the same object identity instead of rebuilding it
|
|
1564
|
+
* peek can depend on the same object identity instead of rebuilding it; so does
|
|
1565
|
+
* an appending list that starts from its page's rows (`hoistInto`), whose first
|
|
1566
|
+
* page is filed in the accumulator under those params.
|
|
1540
1567
|
*
|
|
1541
|
-
* Returns the identifier holding the
|
|
1542
|
-
*
|
|
1568
|
+
* Returns the identifier holding the params when they were hoisted, and the one
|
|
1569
|
+
* holding the peeked rows when this mapper caches.
|
|
1543
1570
|
*/
|
|
1544
1571
|
function pushParamsAttribute(
|
|
1545
1572
|
// tslint:disable-next-line:no-any
|
|
1546
|
-
dp, usage, paramsProps, memoDeps, cacheDeclarations) {
|
|
1573
|
+
dp, usage, paramsProps, memoDeps, cacheDeclarations, hoistInto) {
|
|
1547
1574
|
var _a;
|
|
1548
1575
|
var paramsMemo = types.callExpression(types.identifier('useMemo'), [
|
|
1549
1576
|
types.arrowFunctionExpression([], types.objectExpression(paramsProps)),
|
|
1550
1577
|
types.arrayExpression(memoDeps),
|
|
1551
1578
|
]);
|
|
1552
|
-
// A state-bound sort
|
|
1553
|
-
//
|
|
1554
|
-
//
|
|
1555
|
-
//
|
|
1579
|
+
// A state-bound sort gets no cache peek. The peek is `initialData` by another
|
|
1580
|
+
// name, and such a list takes the server's rows only while its sort is still
|
|
1581
|
+
// where the visitor starts (`buildStartingSortGuard`); the peek was never
|
|
1582
|
+
// extended to it.
|
|
1556
1583
|
var cache = ((_a = usage.cache) === null || _a === void 0 ? void 0 : _a.client) && !usage.dynamicSort ? usage.cache : undefined;
|
|
1557
1584
|
if (!cache) {
|
|
1558
|
-
|
|
1559
|
-
|
|
1585
|
+
if (!hoistInto) {
|
|
1586
|
+
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('params'), types.jsxExpressionContainer(paramsMemo)));
|
|
1587
|
+
return {};
|
|
1588
|
+
}
|
|
1589
|
+
var paramsIdentifier = paramsVarFor(usage.index);
|
|
1590
|
+
hoistInto.push(types.variableDeclaration('const', [
|
|
1591
|
+
types.variableDeclarator(types.identifier(paramsIdentifier), paramsMemo),
|
|
1592
|
+
]));
|
|
1593
|
+
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('params'), types.jsxExpressionContainer(types.identifier(paramsIdentifier))));
|
|
1594
|
+
return { paramsIdentifier: paramsIdentifier };
|
|
1560
1595
|
}
|
|
1561
1596
|
var hoisted = buildCachedParamsDeclarations({ index: usage.index, paramsMemo: paramsMemo, cache: cache });
|
|
1562
1597
|
cacheDeclarations.push.apply(cacheDeclarations, hoisted.declarations);
|
|
1563
1598
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('params'), types.jsxExpressionContainer(types.identifier(hoisted.paramsIdentifier))));
|
|
1564
|
-
return hoisted.cachedIdentifier;
|
|
1599
|
+
return { paramsIdentifier: hoisted.paramsIdentifier, cachedIdentifier: hoisted.cachedIdentifier };
|
|
1600
|
+
}
|
|
1601
|
+
// Whether the rows `getStaticProps` fetched can be this list's first page at
|
|
1602
|
+
// all. A sort bound to state can only be served them when the build knows the
|
|
1603
|
+
// sort the visitor starts with (`startingSort`) and fetched by it; otherwise
|
|
1604
|
+
// the fetch has no sort, and its rows are not the list's first page.
|
|
1605
|
+
function prefetchFollowsSort(usage) {
|
|
1606
|
+
return !usage.dynamicSort || !!usage.startingSort;
|
|
1607
|
+
}
|
|
1608
|
+
// `sortBy === "name-asc"`: the visitor has not moved the sort from where it
|
|
1609
|
+
// starts, so the build-time rows are still its first page. `null` for a list
|
|
1610
|
+
// whose sort the visitor cannot pick, or one that reads no state.
|
|
1611
|
+
function buildStartingSortGuard(usage) {
|
|
1612
|
+
return usage.dynamicSort && usage.startingSort ? buildSortAtStartGuard(usage.startingSort) : null;
|
|
1613
|
+
}
|
|
1614
|
+
// `<condition> && <starting-sort guard>`, or the condition alone.
|
|
1615
|
+
function withStartingSortGuard(condition, usage) {
|
|
1616
|
+
var sortGuard = buildStartingSortGuard(usage);
|
|
1617
|
+
return sortGuard ? types.logicalExpression('&&', condition, sortGuard) : condition;
|
|
1618
|
+
}
|
|
1619
|
+
// An appending list on a page starts from the rows its `getStaticProps`
|
|
1620
|
+
// fetched, when they can be its first page (`prefetchFollowsSort`).
|
|
1621
|
+
function startsFromServerRows(usage) {
|
|
1622
|
+
return usage.infiniteScroll && usage.paginated && prefetchFollowsSort(usage);
|
|
1623
|
+
}
|
|
1624
|
+
/**
|
|
1625
|
+
* `initialData={ds_N_firstPage}` on an appending list, beside the frozen first
|
|
1626
|
+
* page and the effect that files it as page 1 of the accumulator (see
|
|
1627
|
+
* `infinite-scroll.ts`).
|
|
1628
|
+
*
|
|
1629
|
+
* The rows stand in for page 1 only while they answer the list's query: no
|
|
1630
|
+
* search (`queryGuard`), the sort where the visitor starts, no filter set (the
|
|
1631
|
+
* guards the paged lists use), and at least one row — an empty build-time
|
|
1632
|
+
* answer, which a failed fetch also gives, leaves the browser to fetch page 1
|
|
1633
|
+
* as before.
|
|
1634
|
+
*/
|
|
1635
|
+
function pushInfiniteScrollFirstPage(
|
|
1636
|
+
// tslint:disable-next-line:no-any
|
|
1637
|
+
dp, usage, vars, paramsIdentifier, declarations, queryGuard, instanceDeps) {
|
|
1638
|
+
var infiniteVars = getInfiniteScrollVars(usage.index);
|
|
1639
|
+
var serverPayload = function () {
|
|
1640
|
+
return types.optionalMemberExpression(types.identifier('props'), types.identifier(vars.propsPrefix), false, true);
|
|
1641
|
+
};
|
|
1642
|
+
var hasServerRows = types.binaryExpression('>', types.optionalMemberExpression(buildServerRowsExpression(serverPayload(), usage.itemsPath), types.identifier('length'), false, true), types.numericLiteral(0));
|
|
1643
|
+
var startsFromServer = [
|
|
1644
|
+
queryGuard,
|
|
1645
|
+
buildStartingSortGuard(usage),
|
|
1646
|
+
buildNoUrlFilterGuard(usage),
|
|
1647
|
+
hasServerRows,
|
|
1648
|
+
]
|
|
1649
|
+
.filter(function (guard) { return guard !== null; })
|
|
1650
|
+
.reduce(function (all, guard) { return types.logicalExpression('&&', all, guard); });
|
|
1651
|
+
declarations.push(buildFirstPageDeclaration(infiniteVars, startsFromServer, serverPayload(), instanceDeps), buildFirstPageSeedEffect(infiniteVars, paramsIdentifier, usage.perPage, usage.itemsPath));
|
|
1652
|
+
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.identifier(infiniteVars.firstPageVar))));
|
|
1565
1653
|
}
|
|
1566
|
-
function updateDataProviderForPaginatedSearch(dp, usage, vars, fileName, cacheDeclarations, localized) {
|
|
1654
|
+
function updateDataProviderForPaginatedSearch(dp, usage, vars, fileName, cacheDeclarations, localized, firstPageDeclarations) {
|
|
1567
1655
|
var attrs = dp.openingElement.attributes;
|
|
1568
1656
|
// Remove existing params, key, initialData, fetchData, persistDataDuringLoading
|
|
1569
1657
|
dp.openingElement.attributes = attrs.filter(function (attr) {
|
|
@@ -1596,20 +1684,29 @@ function updateDataProviderForPaginatedSearch(dp, usage, vars, fileName, cacheDe
|
|
|
1596
1684
|
if (localized) {
|
|
1597
1685
|
appendClientLocaleParam(paramsProps, memoDeps);
|
|
1598
1686
|
}
|
|
1599
|
-
var
|
|
1600
|
-
|
|
1601
|
-
//
|
|
1602
|
-
//
|
|
1603
|
-
// the
|
|
1604
|
-
//
|
|
1605
|
-
//
|
|
1687
|
+
var seedInto = startsFromServerRows(usage) ? firstPageDeclarations : undefined;
|
|
1688
|
+
var _a = pushParamsAttribute(dp, usage, paramsProps, memoDeps, cacheDeclarations, seedInto), paramsIdentifier = _a.paramsIdentifier, cachedInitialData = _a.cachedIdentifier;
|
|
1689
|
+
// Add initialData: the server-prefetched page 1 while it is the page on show
|
|
1690
|
+
// — page 1, no search, no filter set, and a sort the visitor picks still where
|
|
1691
|
+
// they start (the prefetch ran by that sort). A list whose starting sort the
|
|
1692
|
+
// build cannot know never takes it: that prefetch ran without a sort, so
|
|
1693
|
+
// reusing it would mask the current sort AND make DataProvider skip its first
|
|
1694
|
+
// client fetch (its internal guard only skips when initialData is defined on
|
|
1695
|
+
// mount). Any other sort is fetched fresh, through the useMemo params.
|
|
1606
1696
|
//
|
|
1607
|
-
// An appending list
|
|
1608
|
-
//
|
|
1609
|
-
//
|
|
1610
|
-
//
|
|
1611
|
-
|
|
1612
|
-
|
|
1697
|
+
// An appending list takes its own: `initialData` makes DataProvider skip its
|
|
1698
|
+
// first fetch, so the prefetched page 1 has to be filed in the accumulator
|
|
1699
|
+
// too, or appending page 2 would REPLACE the visible rows with page 2 alone.
|
|
1700
|
+
// The provider remounts per query (its `key`), so the first page is frozen
|
|
1701
|
+
// per query.
|
|
1702
|
+
if (seedInto && paramsIdentifier) {
|
|
1703
|
+
var appliedQuery = function () {
|
|
1704
|
+
return types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('debouncedQuery'));
|
|
1705
|
+
};
|
|
1706
|
+
pushInfiniteScrollFirstPage(dp, usage, vars, paramsIdentifier, seedInto, types.unaryExpression('!', appliedQuery(), true), [appliedQuery()]);
|
|
1707
|
+
}
|
|
1708
|
+
else if (prefetchFollowsSort(usage) && !usage.infiniteScroll) {
|
|
1709
|
+
var initialDataCondition = wrapInitialDataWithUrlFilterGuard(withStartingSortGuard(types.logicalExpression('&&', types.binaryExpression('===', types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('page')), types.numericLiteral(1)), types.unaryExpression('!', types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('debouncedQuery')), true)), usage), usage);
|
|
1613
1710
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.conditionalExpression(initialDataCondition, types.optionalMemberExpression(types.identifier('props'), types.identifier(vars.propsPrefix), false, true), cachedInitialData ? types.identifier(cachedInitialData) : types.identifier('undefined')))));
|
|
1614
1711
|
}
|
|
1615
1712
|
// Add key. Sort is intentionally NOT part of the key — a key change would
|
|
@@ -1647,7 +1744,7 @@ function updateDataProviderForPaginatedSearch(dp, usage, vars, fileName, cacheDe
|
|
|
1647
1744
|
// Add persistDataDuringLoading
|
|
1648
1745
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('persistDataDuringLoading'), types.jsxExpressionContainer(types.booleanLiteral(true))));
|
|
1649
1746
|
}
|
|
1650
|
-
function updateDataProviderForPaginationOnly(dp, usage, vars, fileName, cacheDeclarations, localized) {
|
|
1747
|
+
function updateDataProviderForPaginationOnly(dp, usage, vars, fileName, cacheDeclarations, localized, firstPageDeclarations) {
|
|
1651
1748
|
var attrs = dp.openingElement.attributes;
|
|
1652
1749
|
dp.openingElement.attributes = attrs.filter(function (attr) {
|
|
1653
1750
|
var _a;
|
|
@@ -1676,12 +1773,17 @@ function updateDataProviderForPaginationOnly(dp, usage, vars, fileName, cacheDec
|
|
|
1676
1773
|
appendClientLocaleParam(paramsProps, memoDeps);
|
|
1677
1774
|
}
|
|
1678
1775
|
// Add params
|
|
1679
|
-
var
|
|
1680
|
-
|
|
1681
|
-
//
|
|
1682
|
-
//
|
|
1683
|
-
|
|
1684
|
-
|
|
1776
|
+
var seedInto = startsFromServerRows(usage) ? firstPageDeclarations : undefined;
|
|
1777
|
+
var _a = pushParamsAttribute(dp, usage, paramsProps, memoDeps, cacheDeclarations, seedInto), paramsIdentifier = _a.paramsIdentifier, cachedInitialData = _a.cachedIdentifier;
|
|
1778
|
+
// Add initialData. See paginated+search updater for when a sort the visitor
|
|
1779
|
+
// picks may reuse the prefetch, and how an appending list takes its own. This
|
|
1780
|
+
// provider never remounts (no `key`), so its first page is frozen for the
|
|
1781
|
+
// page's lifetime.
|
|
1782
|
+
if (seedInto && paramsIdentifier) {
|
|
1783
|
+
pushInfiniteScrollFirstPage(dp, usage, vars, paramsIdentifier, seedInto, null, []);
|
|
1784
|
+
}
|
|
1785
|
+
else if (prefetchFollowsSort(usage) && !usage.infiniteScroll) {
|
|
1786
|
+
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.conditionalExpression(wrapInitialDataWithUrlFilterGuard(withStartingSortGuard(types.binaryExpression('===', types.identifier(vars.pageStateVar), types.numericLiteral(1)), usage), usage), types.optionalMemberExpression(types.identifier('props'), types.identifier(vars.propsPrefix), false, true), cachedInitialData ? types.identifier(cachedInitialData) : types.identifier('undefined')))));
|
|
1685
1787
|
}
|
|
1686
1788
|
// Add key — sort is intentionally NOT included; see paginated+search updater,
|
|
1687
1789
|
// which also explains why an appending list keys on nothing at all (there is
|
|
@@ -1731,11 +1833,11 @@ function updateDataProviderForSearchOnly(dp, usage, vars, fileName, cacheDeclara
|
|
|
1731
1833
|
if (localized) {
|
|
1732
1834
|
appendClientLocaleParam(paramsProps, memoDeps);
|
|
1733
1835
|
}
|
|
1734
|
-
var cachedInitialData = pushParamsAttribute(dp, usage, paramsProps, memoDeps, cacheDeclarations);
|
|
1735
|
-
// Add initialData. See paginated+search updater for
|
|
1736
|
-
//
|
|
1737
|
-
if (
|
|
1738
|
-
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.conditionalExpression(wrapInitialDataWithUrlFilterGuard(types.unaryExpression('!', types.identifier(vars.debouncedSearchQueryVar), true), usage), types.optionalMemberExpression(types.identifier('props'), types.identifier(vars.propsPrefix), false, true), cachedInitialData ? types.identifier(cachedInitialData) : types.identifier('undefined')))));
|
|
1836
|
+
var cachedInitialData = pushParamsAttribute(dp, usage, paramsProps, memoDeps, cacheDeclarations).cachedIdentifier;
|
|
1837
|
+
// Add initialData. See paginated+search updater for when a sort the visitor
|
|
1838
|
+
// picks may reuse the prefetch.
|
|
1839
|
+
if (prefetchFollowsSort(usage)) {
|
|
1840
|
+
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.conditionalExpression(wrapInitialDataWithUrlFilterGuard(withStartingSortGuard(types.unaryExpression('!', types.identifier(vars.debouncedSearchQueryVar), true), usage), usage), types.optionalMemberExpression(types.identifier('props'), types.identifier(vars.propsPrefix), false, true), cachedInitialData ? types.identifier(cachedInitialData) : types.identifier('undefined')))));
|
|
1739
1841
|
}
|
|
1740
1842
|
// Add key — sort is intentionally NOT included; see paginated+search updater.
|
|
1741
1843
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(types.templateLiteral([
|
|
@@ -1746,14 +1848,42 @@ function updateDataProviderForSearchOnly(dp, usage, vars, fileName, cacheDeclara
|
|
|
1746
1848
|
dp.openingElement.attributes.push(createFetchDataAttribute(fileName, ((_a = usage.cache) === null || _a === void 0 ? void 0 : _a.client) ? usage.cache : undefined));
|
|
1747
1849
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('persistDataDuringLoading'), types.jsxExpressionContainer(types.booleanLiteral(true))));
|
|
1748
1850
|
}
|
|
1851
|
+
/**
|
|
1852
|
+
* A plain list on a page is seeded with the rows its `getStaticProps` fetched
|
|
1853
|
+
* (`extractDataSourceIntoGetStaticProps`), and a seeded provider skips its first
|
|
1854
|
+
* fetch. With a sort the visitor picks, those rows are the list's only while the
|
|
1855
|
+
* sort is where a visitor starts — the build fetched them by it:
|
|
1856
|
+
*
|
|
1857
|
+
* initialData={sortBy === "name-asc" ? props.items_products : undefined}
|
|
1858
|
+
*
|
|
1859
|
+
* — and any other sort is fetched fresh, through the params it changes. When the
|
|
1860
|
+
* build cannot know where the sort starts (`prefetchFollowsSort`), it fetched
|
|
1861
|
+
* the rows unsorted, and the list is never seeded with them. A plain list has no
|
|
1862
|
+
* search, and is only seeded without a filter a visitor sets.
|
|
1863
|
+
*/
|
|
1864
|
+
function seedPlainListWhileSortStarts(dp, usage) {
|
|
1865
|
+
if (!usage.dynamicSort) {
|
|
1866
|
+
return;
|
|
1867
|
+
}
|
|
1868
|
+
var attrs = dp.openingElement.attributes;
|
|
1869
|
+
var index = attrs.findIndex(function (attr) { var _a; return attr.type === 'JSXAttribute' && ((_a = attr.name) === null || _a === void 0 ? void 0 : _a.name) === 'initialData'; });
|
|
1870
|
+
if (index === -1) {
|
|
1871
|
+
return;
|
|
1872
|
+
}
|
|
1873
|
+
if (!prefetchFollowsSort(usage)) {
|
|
1874
|
+
attrs.splice(index, 1);
|
|
1875
|
+
return;
|
|
1876
|
+
}
|
|
1877
|
+
var sortGuard = buildStartingSortGuard(usage);
|
|
1878
|
+
var seeded = attrs[index].value;
|
|
1879
|
+
if (!sortGuard || (seeded === null || seeded === void 0 ? void 0 : seeded.type) !== 'JSXExpressionContainer') {
|
|
1880
|
+
return;
|
|
1881
|
+
}
|
|
1882
|
+
attrs[index] = types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.conditionalExpression(sortGuard, seeded.expression, types.identifier('undefined'))));
|
|
1883
|
+
}
|
|
1749
1884
|
function updateDataProviderForPlain(dp, fileName, usage, localized) {
|
|
1750
1885
|
var _a, _b, _c, _d, _e, _f;
|
|
1751
|
-
|
|
1752
|
-
// pre-rendered in the table's order would stand in for it, since a seeded
|
|
1753
|
-
// provider skips its first fetch — the paginated lists drop them the same way.
|
|
1754
|
-
if (usage.dynamicSort) {
|
|
1755
|
-
dp.openingElement.attributes = dp.openingElement.attributes.filter(function (attr) { var _a; return !(attr.type === 'JSXAttribute' && ((_a = attr.name) === null || _a === void 0 ? void 0 : _a.name) === 'initialData'); });
|
|
1756
|
-
}
|
|
1886
|
+
seedPlainListWhileSortStarts(dp, usage);
|
|
1757
1887
|
var attrs = dp.openingElement.attributes;
|
|
1758
1888
|
var clientCache = ((_a = usage.cache) === null || _a === void 0 ? void 0 : _a.client) ? usage.cache : undefined;
|
|
1759
1889
|
// Check if fetchData already exists
|
|
@@ -1906,21 +2036,18 @@ accumulate) {
|
|
|
1906
2036
|
? buildCacheStoreThen(cache)
|
|
1907
2037
|
: uncachedTail;
|
|
1908
2038
|
var networkChain = types.callExpression(types.memberExpression(parsedJson, types.identifier('then')), [responseTail]);
|
|
2039
|
+
// An appending list records the request it now stands on before making it
|
|
2040
|
+
// (see `buildAccumulatingRequestMark`).
|
|
1909
2041
|
var arrow = cache
|
|
1910
2042
|
? types.arrowFunctionExpression([types.identifier('params')], buildCachedFetchBody(networkChain, cache))
|
|
1911
|
-
:
|
|
2043
|
+
: accumulate
|
|
2044
|
+
? types.arrowFunctionExpression([types.identifier('params')], types.blockStatement([
|
|
2045
|
+
buildAccumulatingRequestMark(getInfiniteScrollVars(accumulate.usage.index)),
|
|
2046
|
+
types.returnStatement(networkChain),
|
|
2047
|
+
]))
|
|
2048
|
+
: types.arrowFunctionExpression([types.identifier('params')], networkChain);
|
|
1912
2049
|
return types.jsxAttribute(types.jsxIdentifier('fetchData'), types.jsxExpressionContainer(types.callExpression(types.identifier('useCallback'), [arrow, types.arrayExpression([])])));
|
|
1913
2050
|
}
|
|
1914
|
-
function wireSearchInput(inputNode, vars) {
|
|
1915
|
-
// Remove existing onChange and value
|
|
1916
|
-
inputNode.openingElement.attributes = inputNode.openingElement.attributes.filter(function (attr) { var _a; return !['onChange', 'value'].includes((_a = attr.name) === null || _a === void 0 ? void 0 : _a.name); });
|
|
1917
|
-
// Add onChange
|
|
1918
|
-
inputNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onChange'), types.jsxExpressionContainer(types.arrowFunctionExpression([types.identifier('e')], types.callExpression(types.identifier(vars.setSearchQueryVar), [
|
|
1919
|
-
types.memberExpression(types.memberExpression(types.identifier('e'), types.identifier('target')), types.identifier('value')),
|
|
1920
|
-
])))));
|
|
1921
|
-
// Add value
|
|
1922
|
-
inputNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('value'), types.jsxExpressionContainer(types.identifier(vars.searchQueryVar))));
|
|
1923
|
-
}
|
|
1924
2051
|
/**
|
|
1925
2052
|
* The `fetchData` attribute for one paginated usage.
|
|
1926
2053
|
*
|
|
@@ -1936,6 +2063,32 @@ function buildFetchDataForUsage(fileName, usage) {
|
|
|
1936
2063
|
}
|
|
1937
2064
|
return createFetchDataAttribute(fileName, ((_a = usage.cache) === null || _a === void 0 ? void 0 : _a.client) ? usage.cache : undefined);
|
|
1938
2065
|
}
|
|
2066
|
+
/** `const [ds_N_total, setDs_N_total] = useState(null)` — declared only beside a range control. */
|
|
2067
|
+
function buildTotalDeclaration(vars) {
|
|
2068
|
+
return types.variableDeclaration('const', [
|
|
2069
|
+
types.variableDeclarator(types.arrayPattern([
|
|
2070
|
+
types.identifier(vars.totalStateVar),
|
|
2071
|
+
types.identifier(vars.setTotalStateVar),
|
|
2072
|
+
]), types.callExpression(types.identifier('useState'), [types.nullLiteral()])),
|
|
2073
|
+
]);
|
|
2074
|
+
}
|
|
2075
|
+
/**
|
|
2076
|
+
* Fills one `range` text with the live row range of `usage` (see
|
|
2077
|
+
* `range-control.ts`). A mapper that does not page has no count to show, so
|
|
2078
|
+
* its range text is left as drawn.
|
|
2079
|
+
*/
|
|
2080
|
+
function wireRangeControlFor(control, usage, vars) {
|
|
2081
|
+
if (!usage.paginated) {
|
|
2082
|
+
return;
|
|
2083
|
+
}
|
|
2084
|
+
var currentPageExpr = getPageAccessors(usage, vars).currentPageExpr;
|
|
2085
|
+
wireRangeControl(control, {
|
|
2086
|
+
totalVar: vars.totalStateVar,
|
|
2087
|
+
currentPageExpr: currentPageExpr(),
|
|
2088
|
+
perPage: usage.perPage,
|
|
2089
|
+
infiniteScroll: usage.infiniteScroll,
|
|
2090
|
+
});
|
|
2091
|
+
}
|
|
1939
2092
|
/**
|
|
1940
2093
|
* Wires the authored Load More button of an appending list.
|
|
1941
2094
|
*
|
|
@@ -1975,6 +2128,11 @@ function wireLoadMoreButton(paginationNode, usage, vars, hasLoadingState) {
|
|
|
1975
2128
|
* buttons beside its Load More.
|
|
1976
2129
|
*/
|
|
1977
2130
|
function wirePaginationWidget(paginationNode, usage, vars, hasLoadingState) {
|
|
2131
|
+
// A range text inside the container takes the container's owner, like the
|
|
2132
|
+
// buttons beside it; one naming its own mapper is wired in STEP 5b instead.
|
|
2133
|
+
findAllPaginationControls(paginationNode, 'range')
|
|
2134
|
+
.filter(function (control) { return !readJSXAttributeString(control, PAGINATION_FOR_ATTR); })
|
|
2135
|
+
.forEach(function (control) { return wireRangeControlFor(control, usage, vars); });
|
|
1978
2136
|
if (usage.infiniteScroll) {
|
|
1979
2137
|
// Only the Load More button survives; page controls make no sense for a
|
|
1980
2138
|
// list the visitor never leaves.
|
|
@@ -2179,7 +2337,15 @@ function ensureAPIRouteExists(extractedResources, usage, dataSources, transformO
|
|
|
2179
2337
|
};
|
|
2180
2338
|
}
|
|
2181
2339
|
}
|
|
2182
|
-
|
|
2340
|
+
// `fetchCount(<params>, <read arguments>)`: the params may be left out only
|
|
2341
|
+
// when nothing follows them.
|
|
2342
|
+
var countReadArguments = function (countParams, readArguments) {
|
|
2343
|
+
return countParams.length > 0 || readArguments.length > 0
|
|
2344
|
+
? __spreadArray([types.objectExpression(countParams)], readArguments, true) : [];
|
|
2345
|
+
};
|
|
2346
|
+
function updateGetStaticProps(chunks, registry, dependencies, folderPath, localized,
|
|
2347
|
+
// The arguments every read hands the module after its params (fresh nodes per call).
|
|
2348
|
+
readArguments) {
|
|
2183
2349
|
var _a;
|
|
2184
2350
|
var getStaticPropsChunk = chunks.find(function (c) { return c.name === 'getStaticProps'; });
|
|
2185
2351
|
if (!getStaticPropsChunk || getStaticPropsChunk.type !== ChunkType.AST) {
|
|
@@ -2260,6 +2426,12 @@ function updateGetStaticProps(chunks, registry, dependencies, folderPath, locali
|
|
|
2260
2426
|
})),
|
|
2261
2427
|
])));
|
|
2262
2428
|
}
|
|
2429
|
+
else if (usage.dynamicSort && usage.startingSort) {
|
|
2430
|
+
// A sort the visitor picks: page 1 by the sort they start with, sent
|
|
2431
|
+
// as the very string the browser sends for it, so page 2 continues
|
|
2432
|
+
// this page exactly (see `buildStartingSortsValue`).
|
|
2433
|
+
fetchParams.push(types.objectProperty(types.identifier('sorts'), buildStartingSortsValue(usage.dynamicSort, usage.startingSort)));
|
|
2434
|
+
}
|
|
2263
2435
|
// Add filters if present
|
|
2264
2436
|
// Filter out dynamic destinations for getStaticProps (they can't be resolved at build time)
|
|
2265
2437
|
var staticFilters = staticFiltersOf(usage);
|
|
@@ -2275,7 +2447,7 @@ function updateGetStaticProps(chunks, registry, dependencies, folderPath, locali
|
|
|
2275
2447
|
var existingFetchIndex = arrayPattern.elements.findIndex(function (el) { return (el === null || el === void 0 ? void 0 : el.type) === 'Identifier' && el.name === vars.propsPrefix; });
|
|
2276
2448
|
if (existingFetchIndex === -1) {
|
|
2277
2449
|
arrayPattern.elements.push(types.identifier(vars.propsPrefix));
|
|
2278
|
-
fetchesArray.elements.push(types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.identifier(fetcherImportName), types.identifier('fetchData')), [types.objectExpression(fetchParams)]), types.identifier('catch')), [
|
|
2450
|
+
fetchesArray.elements.push(types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.identifier(fetcherImportName), types.identifier('fetchData')), __spreadArray([types.objectExpression(fetchParams)], readArguments(), true)), types.identifier('catch')), [
|
|
2279
2451
|
types.arrowFunctionExpression([types.identifier('error')], types.blockStatement([
|
|
2280
2452
|
types.expressionStatement(types.callExpression(types.memberExpression(types.identifier('console'), types.identifier('error')), [
|
|
2281
2453
|
types.stringLiteral("Error fetching ".concat(vars.propsPrefix, ":")),
|
|
@@ -2378,7 +2550,7 @@ function updateGetStaticProps(chunks, registry, dependencies, folderPath, locali
|
|
|
2378
2550
|
countParams.push(types.objectProperty(types.identifier('filters'), buildStaticFiltersStringifyCall(staticFiltersForCount)));
|
|
2379
2551
|
}
|
|
2380
2552
|
appendItemsPathParam(countParams, firstUsage.itemsPath, 'collectionPath');
|
|
2381
|
-
fetchesArray.elements.push(types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.identifier(fetcherImportName), types.identifier('fetchCount')), countParams
|
|
2553
|
+
fetchesArray.elements.push(types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.identifier(fetcherImportName), types.identifier('fetchCount')), countReadArguments(countParams, readArguments())), types.identifier('catch')), [
|
|
2382
2554
|
types.arrowFunctionExpression([types.identifier('error')], types.blockStatement([
|
|
2383
2555
|
types.expressionStatement(types.callExpression(types.memberExpression(types.identifier('console'), types.identifier('error')), [
|
|
2384
2556
|
types.stringLiteral("Error fetching ".concat(countVarName, ":")),
|