@teleporthq/teleport-plugin-next-data-source 0.43.3 → 0.43.17
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__/filter-utils.test.ts +43 -1
- package/dist/cjs/filter-utils.d.ts +1 -0
- package/dist/cjs/filter-utils.d.ts.map +1 -1
- package/dist/cjs/filter-utils.js +24 -1
- package/dist/cjs/filter-utils.js.map +1 -1
- package/dist/cjs/pagination-plugin.d.ts.map +1 -1
- package/dist/cjs/pagination-plugin.js +31 -4
- package/dist/cjs/pagination-plugin.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/filter-utils.d.ts +1 -0
- package/dist/esm/filter-utils.d.ts.map +1 -1
- package/dist/esm/filter-utils.js +22 -0
- package/dist/esm/filter-utils.js.map +1 -1
- package/dist/esm/pagination-plugin.d.ts.map +1 -1
- package/dist/esm/pagination-plugin.js +32 -5
- package/dist/esm/pagination-plugin.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/src/filter-utils.ts +26 -0
- package/src/pagination-plugin.ts +49 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teleporthq/teleport-plugin-next-data-source",
|
|
3
|
-
"version": "0.43.
|
|
3
|
+
"version": "0.43.17",
|
|
4
4
|
"description": "A plugin for managing data sources for Next.js projects.",
|
|
5
5
|
"author": "teleportHQ",
|
|
6
6
|
"license": "MIT",
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@babel/parser": "^7.26.10",
|
|
28
28
|
"@babel/types": "^7.5.5",
|
|
29
|
-
"@teleporthq/teleport-plugin-common": "^0.43.
|
|
30
|
-
"@teleporthq/teleport-shared": "^0.43.
|
|
31
|
-
"@teleporthq/teleport-types": "^0.43.
|
|
29
|
+
"@teleporthq/teleport-plugin-common": "^0.43.14",
|
|
30
|
+
"@teleporthq/teleport-shared": "^0.43.14",
|
|
31
|
+
"@teleporthq/teleport-types": "^0.43.14"
|
|
32
32
|
},
|
|
33
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "4d8f9c7c3ed32501117a692b0d4de38ac3387a02"
|
|
34
34
|
}
|
package/src/filter-utils.ts
CHANGED
|
@@ -109,3 +109,29 @@ export const pushStateIdsAsDeps = (
|
|
|
109
109
|
deps.push(types.identifier(id))
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
|
+
|
|
113
|
+
// Appends each id in `propIds` as a `props.<id>` MemberExpression onto `deps`,
|
|
114
|
+
// skipping any already tracked in `seen` (keyed by `props.<id>` so a prop and a
|
|
115
|
+
// same-named state var never collide). Mutates both `deps` and `seen`.
|
|
116
|
+
//
|
|
117
|
+
// Prop-bound filter destinations resolve to `props.<id>` on the VALUE side (see
|
|
118
|
+
// `convertFilterDestinationToExpression` in teleport-plugin-common), so the
|
|
119
|
+
// useMemo/useEffect dependency MUST reference the exact same `props.<id>`
|
|
120
|
+
// member. Emitting a bare `<id>` identifier (as `pushStateIdsAsDeps` does for
|
|
121
|
+
// state) references an undeclared symbol — props are never destructured into
|
|
122
|
+
// the component scope — which crashed prerender with
|
|
123
|
+
// `ReferenceError: <id> is not defined`.
|
|
124
|
+
export const pushPropIdsAsDeps = (
|
|
125
|
+
deps: types.Expression[],
|
|
126
|
+
seen: Set<string>,
|
|
127
|
+
propIds: string[]
|
|
128
|
+
): void => {
|
|
129
|
+
for (const id of propIds) {
|
|
130
|
+
const key = `props.${id}`
|
|
131
|
+
if (seen.has(key)) {
|
|
132
|
+
continue
|
|
133
|
+
}
|
|
134
|
+
seen.add(key)
|
|
135
|
+
deps.push(types.memberExpression(types.identifier('props'), types.identifier(id)))
|
|
136
|
+
}
|
|
137
|
+
}
|
package/src/pagination-plugin.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { ASTUtils } from '@teleporthq/teleport-plugin-common'
|
|
|
11
11
|
import { generateSafeFileName } from './utils'
|
|
12
12
|
import { generateDataSourceFetcherWithCore } from './data-source-fetchers'
|
|
13
13
|
import { appendSortsParam, DynamicSortAST, extractDynamicSort } from './sort-utils'
|
|
14
|
-
import { appendFiltersParam, pushStateIdsAsDeps } from './filter-utils'
|
|
14
|
+
import { appendFiltersParam, pushStateIdsAsDeps, pushPropIdsAsDeps } from './filter-utils'
|
|
15
15
|
|
|
16
16
|
// ----- searchDefaultValue support -----
|
|
17
17
|
//
|
|
@@ -109,10 +109,17 @@ interface DataSourceUsage {
|
|
|
109
109
|
// tslint:disable-next-line:no-any
|
|
110
110
|
filters: any[]
|
|
111
111
|
// State IDs from dynamic filter destinations (for useMemo dependencies).
|
|
112
|
-
// Only state references land here;
|
|
113
|
-
// `
|
|
114
|
-
// `
|
|
112
|
+
// Only `state` references land here; their dep/guard expression is a bare
|
|
113
|
+
// identifier. `prop` refs go to `filterPropIds` (dep expression `props.<id>`)
|
|
114
|
+
// and `urlSearchParams` refs to `filterUrlSearchParamKeys` (dep expression
|
|
115
|
+
// `router.query.<key>`), because each resolves to a different scope.
|
|
115
116
|
filterStateIds: string[]
|
|
117
|
+
// Prop IDs from dynamic filter destinations. Kept separate from
|
|
118
|
+
// `filterStateIds` so their dep/guard expression is `props.<id>` (matching the
|
|
119
|
+
// VALUE side in `convertFilterDestinationToExpression`) rather than a bare
|
|
120
|
+
// identifier — a bare `<id>` is undefined in the component scope and crashes
|
|
121
|
+
// prerender with `ReferenceError: <id> is not defined`.
|
|
122
|
+
filterPropIds: string[]
|
|
116
123
|
// URL search-param keys referenced by filter destinations (e.g.
|
|
117
124
|
// `'categoryFilter'`). Drives `const router = useRouter()` injection and
|
|
118
125
|
// the corresponding `router.query.<key>` entries in `useMemo` deps so the
|
|
@@ -249,7 +256,11 @@ function pushUrlSearchParamMemoDeps(memoDeps: types.Expression[], usage: DataSou
|
|
|
249
256
|
// callers fall back to the existing `props.X` expression unchanged so
|
|
250
257
|
// non-filtered pages still benefit from the SSR prefetch.
|
|
251
258
|
function buildNoUrlFilterGuard(usage: DataSourceUsage): types.Expression | null {
|
|
252
|
-
if (
|
|
259
|
+
if (
|
|
260
|
+
usage.filterUrlSearchParamKeys.length === 0 &&
|
|
261
|
+
usage.filterStateIds.length === 0 &&
|
|
262
|
+
usage.filterPropIds.length === 0
|
|
263
|
+
) {
|
|
253
264
|
return null
|
|
254
265
|
}
|
|
255
266
|
const guards: types.Expression[] = []
|
|
@@ -274,6 +285,18 @@ function buildNoUrlFilterGuard(usage: DataSourceUsage): types.Expression | null
|
|
|
274
285
|
for (const id of usage.filterStateIds) {
|
|
275
286
|
guards.push(types.unaryExpression('!', types.identifier(id), true))
|
|
276
287
|
}
|
|
288
|
+
// Prop-bound filter destinations read `props.<id>` (a constant per page
|
|
289
|
+
// instance), so the guard is `!props.<id>` — mirroring the value expression
|
|
290
|
+
// exactly so the bare-identifier ReferenceError can't reappear here.
|
|
291
|
+
for (const id of usage.filterPropIds) {
|
|
292
|
+
guards.push(
|
|
293
|
+
types.unaryExpression(
|
|
294
|
+
'!',
|
|
295
|
+
types.memberExpression(types.identifier('props'), types.identifier(id)),
|
|
296
|
+
true
|
|
297
|
+
)
|
|
298
|
+
)
|
|
299
|
+
}
|
|
277
300
|
return guards.reduce((acc, next) => types.logicalExpression('&&', acc, next))
|
|
278
301
|
}
|
|
279
302
|
|
|
@@ -417,6 +440,7 @@ function buildStateRegistry(uidlNode: any): StateRegistry {
|
|
|
417
440
|
// `urlSearchParams` refs resolve to `router.query.<key>` and need a
|
|
418
441
|
// `useRouter()` declaration injected separately.
|
|
419
442
|
const filterStateIds: string[] = []
|
|
443
|
+
const filterPropIds: string[] = []
|
|
420
444
|
for (const f of filters) {
|
|
421
445
|
if (!ASTUtils.isUIDLDynamicReference(f.destination)) {
|
|
422
446
|
continue
|
|
@@ -430,6 +454,13 @@ function buildStateRegistry(uidlNode: any): StateRegistry {
|
|
|
430
454
|
if (destinationContent.referenceType === 'urlSearchParams') {
|
|
431
455
|
continue
|
|
432
456
|
}
|
|
457
|
+
// `prop` destinations resolve to `props.<id>` (see
|
|
458
|
+
// buildFilterDestinationExpression / convertFilterDestinationToExpression),
|
|
459
|
+
// so they must NOT be emitted as bare deps. Route them to filterPropIds.
|
|
460
|
+
if (destinationContent.referenceType === 'prop') {
|
|
461
|
+
filterPropIds.push(destinationContent.id)
|
|
462
|
+
continue
|
|
463
|
+
}
|
|
433
464
|
filterStateIds.push(destinationContent.id)
|
|
434
465
|
}
|
|
435
466
|
const filterUrlSearchParamKeys: string[] = collectFilterUrlSearchParamKeys(filters)
|
|
@@ -465,6 +496,7 @@ function buildStateRegistry(uidlNode: any): StateRegistry {
|
|
|
465
496
|
dynamicSort,
|
|
466
497
|
filters,
|
|
467
498
|
filterStateIds,
|
|
499
|
+
filterPropIds,
|
|
468
500
|
filterUrlSearchParamKeys,
|
|
469
501
|
category: 'plain',
|
|
470
502
|
}
|
|
@@ -1010,7 +1042,9 @@ export const createNextArrayMapperPaginationPlugin: ComponentPluginFactory<{}> =
|
|
|
1010
1042
|
// deps, ds_0_maxPages stays at the original count and the "Next"
|
|
1011
1043
|
// button stays enabled past the actual last page of the filtered
|
|
1012
1044
|
// results — letting the user click into empty pages.
|
|
1013
|
-
|
|
1045
|
+
const countEffectSeen = new Set<string>()
|
|
1046
|
+
pushStateIdsAsDeps(countEffectDeps, countEffectSeen, usage.filterStateIds)
|
|
1047
|
+
pushPropIdsAsDeps(countEffectDeps, countEffectSeen, usage.filterPropIds)
|
|
1014
1048
|
// Same goes for URL-driven filters (already documented above).
|
|
1015
1049
|
pushUrlSearchParamMemoDeps(countEffectDeps, usage)
|
|
1016
1050
|
effectStatements.push(
|
|
@@ -1165,7 +1199,9 @@ export const createNextArrayMapperPaginationPlugin: ComponentPluginFactory<{}> =
|
|
|
1165
1199
|
types.arrayExpression(
|
|
1166
1200
|
((): types.Expression[] => {
|
|
1167
1201
|
const deps: types.Expression[] = []
|
|
1168
|
-
|
|
1202
|
+
const depsSeen = new Set<string>()
|
|
1203
|
+
pushStateIdsAsDeps(deps, depsSeen, usage.filterStateIds)
|
|
1204
|
+
pushPropIdsAsDeps(deps, depsSeen, usage.filterPropIds)
|
|
1169
1205
|
pushUrlSearchParamMemoDeps(deps, usage)
|
|
1170
1206
|
return deps
|
|
1171
1207
|
})()
|
|
@@ -1698,6 +1734,7 @@ function updateDataProviderForPaginatedSearch(
|
|
|
1698
1734
|
const memoDeps: types.Expression[] = [types.identifier(vars.combinedStateVar)]
|
|
1699
1735
|
const seenDeps = new Set<string>([vars.combinedStateVar])
|
|
1700
1736
|
pushStateIdsAsDeps(memoDeps, seenDeps, usage.filterStateIds)
|
|
1737
|
+
pushPropIdsAsDeps(memoDeps, seenDeps, usage.filterPropIds)
|
|
1701
1738
|
if (usage.dynamicSort) {
|
|
1702
1739
|
pushStateIdsAsDeps(memoDeps, seenDeps, usage.dynamicSort.depStateIds)
|
|
1703
1740
|
}
|
|
@@ -1836,6 +1873,7 @@ function updateDataProviderForPaginationOnly(
|
|
|
1836
1873
|
const memoDeps: types.Expression[] = [types.identifier(vars.pageStateVar)]
|
|
1837
1874
|
const seenDeps = new Set<string>([vars.pageStateVar])
|
|
1838
1875
|
pushStateIdsAsDeps(memoDeps, seenDeps, usage.filterStateIds)
|
|
1876
|
+
pushPropIdsAsDeps(memoDeps, seenDeps, usage.filterPropIds)
|
|
1839
1877
|
if (usage.dynamicSort) {
|
|
1840
1878
|
pushStateIdsAsDeps(memoDeps, seenDeps, usage.dynamicSort.depStateIds)
|
|
1841
1879
|
}
|
|
@@ -1954,6 +1992,7 @@ function updateDataProviderForSearchOnly(
|
|
|
1954
1992
|
const memoDeps: types.Expression[] = [types.identifier(vars.debouncedSearchQueryVar)]
|
|
1955
1993
|
const seenDeps = new Set<string>([vars.debouncedSearchQueryVar])
|
|
1956
1994
|
pushStateIdsAsDeps(memoDeps, seenDeps, usage.filterStateIds)
|
|
1995
|
+
pushPropIdsAsDeps(memoDeps, seenDeps, usage.filterPropIds)
|
|
1957
1996
|
if (usage.dynamicSort) {
|
|
1958
1997
|
pushStateIdsAsDeps(memoDeps, seenDeps, usage.dynamicSort.depStateIds)
|
|
1959
1998
|
}
|
|
@@ -2084,7 +2123,9 @@ function updateDataProviderForPlain(dp: any, fileName: string, usage: DataSource
|
|
|
2084
2123
|
|
|
2085
2124
|
// Build useMemo dependencies including filter state IDs
|
|
2086
2125
|
const memoDeps: types.Expression[] = []
|
|
2087
|
-
|
|
2126
|
+
const memoSeen = new Set<string>()
|
|
2127
|
+
pushStateIdsAsDeps(memoDeps, memoSeen, usage.filterStateIds)
|
|
2128
|
+
pushPropIdsAsDeps(memoDeps, memoSeen, usage.filterPropIds)
|
|
2088
2129
|
pushUrlSearchParamMemoDeps(memoDeps, usage)
|
|
2089
2130
|
|
|
2090
2131
|
// Wrap params in useMemo with filter state dependencies
|