@teleporthq/teleport-plugin-next-data-source 0.43.42 → 0.43.46
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__/ecommerce-product-variant-swatch.test.ts +93 -0
- package/__tests__/fetchers.test.ts +11 -0
- package/dist/cjs/array-mapper-registry.d.ts +0 -1
- package/dist/cjs/array-mapper-registry.d.ts.map +1 -1
- package/dist/cjs/array-mapper-registry.js +0 -3
- package/dist/cjs/array-mapper-registry.js.map +1 -1
- package/dist/cjs/data-source-fetchers.d.ts +3 -3
- package/dist/cjs/data-source-fetchers.d.ts.map +1 -1
- package/dist/cjs/data-source-fetchers.js +4 -4
- package/dist/cjs/data-source-fetchers.js.map +1 -1
- package/dist/cjs/fetchers/postgresql.d.ts.map +1 -1
- package/dist/cjs/fetchers/postgresql.js +1 -1
- package/dist/cjs/fetchers/postgresql.js.map +1 -1
- package/dist/cjs/fetchers/teleport.d.ts +2 -1
- package/dist/cjs/fetchers/teleport.d.ts.map +1 -1
- package/dist/cjs/fetchers/teleport.js +3 -3
- package/dist/cjs/fetchers/teleport.js.map +1 -1
- package/dist/cjs/filter-utils.d.ts.map +1 -1
- package/dist/cjs/filter-utils.js +12 -3
- package/dist/cjs/filter-utils.js.map +1 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +8 -7
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/pagination-plugin.d.ts.map +1 -1
- package/dist/cjs/pagination-plugin.js +12 -19
- package/dist/cjs/pagination-plugin.js.map +1 -1
- package/dist/cjs/transformations/ecommerce-product.d.ts +2 -1
- package/dist/cjs/transformations/ecommerce-product.d.ts.map +1 -1
- package/dist/cjs/transformations/ecommerce-product.js +36 -2
- package/dist/cjs/transformations/ecommerce-product.js.map +1 -1
- package/dist/cjs/transformations/index.d.ts +2 -1
- package/dist/cjs/transformations/index.d.ts.map +1 -1
- package/dist/cjs/transformations/index.js +9 -3
- package/dist/cjs/transformations/index.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils.d.ts +3 -3
- package/dist/cjs/utils.d.ts.map +1 -1
- package/dist/cjs/utils.js +4 -4
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/array-mapper-registry.d.ts +0 -1
- package/dist/esm/array-mapper-registry.d.ts.map +1 -1
- package/dist/esm/array-mapper-registry.js +0 -3
- package/dist/esm/array-mapper-registry.js.map +1 -1
- package/dist/esm/data-source-fetchers.d.ts +3 -3
- package/dist/esm/data-source-fetchers.d.ts.map +1 -1
- package/dist/esm/data-source-fetchers.js +4 -4
- package/dist/esm/data-source-fetchers.js.map +1 -1
- package/dist/esm/fetchers/postgresql.d.ts.map +1 -1
- package/dist/esm/fetchers/postgresql.js +1 -1
- package/dist/esm/fetchers/postgresql.js.map +1 -1
- package/dist/esm/fetchers/teleport.d.ts +2 -1
- package/dist/esm/fetchers/teleport.d.ts.map +1 -1
- package/dist/esm/fetchers/teleport.js +3 -3
- package/dist/esm/fetchers/teleport.js.map +1 -1
- package/dist/esm/filter-utils.d.ts.map +1 -1
- package/dist/esm/filter-utils.js +12 -3
- package/dist/esm/filter-utils.js.map +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +8 -7
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/pagination-plugin.d.ts.map +1 -1
- package/dist/esm/pagination-plugin.js +12 -19
- package/dist/esm/pagination-plugin.js.map +1 -1
- package/dist/esm/transformations/ecommerce-product.d.ts +2 -1
- package/dist/esm/transformations/ecommerce-product.d.ts.map +1 -1
- package/dist/esm/transformations/ecommerce-product.js +36 -2
- package/dist/esm/transformations/ecommerce-product.js.map +1 -1
- package/dist/esm/transformations/index.d.ts +2 -1
- package/dist/esm/transformations/index.d.ts.map +1 -1
- package/dist/esm/transformations/index.js +9 -3
- package/dist/esm/transformations/index.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils.d.ts +3 -3
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/esm/utils.js +4 -4
- package/dist/esm/utils.js.map +1 -1
- package/package.json +5 -5
- package/src/array-mapper-registry.ts +0 -5
- package/src/data-source-fetchers.ts +10 -5
- package/src/fetchers/postgresql.ts +17 -0
- package/src/fetchers/teleport.ts +38 -3
- package/src/filter-utils.ts +32 -5
- package/src/index.ts +9 -4
- package/src/pagination-plugin.ts +20 -42
- package/src/transformations/ecommerce-product.ts +430 -1
- package/src/transformations/index.ts +28 -4
- package/src/utils.ts +12 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DataSourceType, UIDLDataSource } from '@teleporthq/teleport-types'
|
|
1
|
+
import { DataSourceType, UIDLDataSource, UIDLEcommerceCategory } from '@teleporthq/teleport-types'
|
|
2
2
|
import {
|
|
3
3
|
generatePostgreSQLFetcher,
|
|
4
4
|
generateMySQLFetcher,
|
|
@@ -78,7 +78,11 @@ export const getDataSourceDependencies = (
|
|
|
78
78
|
return dependencyMap[type]
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
export function generateDataSourceFetcher(
|
|
81
|
+
export function generateDataSourceFetcher(
|
|
82
|
+
dataSource: UIDLDataSource,
|
|
83
|
+
tableName: string,
|
|
84
|
+
categories?: UIDLEcommerceCategory[]
|
|
85
|
+
): string {
|
|
82
86
|
if (!dataSource || typeof dataSource !== 'object') {
|
|
83
87
|
throw new Error('Invalid data source: data source must be a valid object')
|
|
84
88
|
}
|
|
@@ -233,7 +237,7 @@ export function generateDataSourceFetcher(dataSource: UIDLDataSource, tableName:
|
|
|
233
237
|
if (!validation.isValid) {
|
|
234
238
|
throw new Error(`Teleport config validation failed: ${validation.error}`)
|
|
235
239
|
}
|
|
236
|
-
return generateTeleportFetcher(config, tableName)
|
|
240
|
+
return generateTeleportFetcher(config, tableName, categories)
|
|
237
241
|
}
|
|
238
242
|
|
|
239
243
|
default:
|
|
@@ -253,9 +257,10 @@ export function generateDataSourceFetcher(dataSource: UIDLDataSource, tableName:
|
|
|
253
257
|
export function generateDataSourceFetcherWithCore(
|
|
254
258
|
dataSource: UIDLDataSource,
|
|
255
259
|
tableName: string,
|
|
256
|
-
isApiRoute: boolean = false
|
|
260
|
+
isApiRoute: boolean = false,
|
|
261
|
+
categories?: UIDLEcommerceCategory[]
|
|
257
262
|
): string {
|
|
258
|
-
const apiHandler = generateDataSourceFetcher(dataSource, tableName)
|
|
263
|
+
const apiHandler = generateDataSourceFetcher(dataSource, tableName, categories)
|
|
259
264
|
|
|
260
265
|
// Extract the handler function body from the API route
|
|
261
266
|
// The API route is structured as: export default async function handler(req, res) { ... }
|
|
@@ -75,6 +75,12 @@ const processFilters = (filters, conditions, queryParams, paramIndex) => {
|
|
|
75
75
|
|
|
76
76
|
if (Array.isArray(value)) {
|
|
77
77
|
if (value.length === 0) return
|
|
78
|
+
if (operand === 'array_overlap') {
|
|
79
|
+
conditions.push(\`jsonb_exists_any(NULLIF(\${field}, '')::jsonb, $\${paramIndex}::text[])\`)
|
|
80
|
+
queryParams.push(value.map((entry) => String(entry)))
|
|
81
|
+
paramIndex++
|
|
82
|
+
return
|
|
83
|
+
}
|
|
78
84
|
const placeholders = value.map(() => \`$\${paramIndex++}\`)
|
|
79
85
|
queryParams.push(...value)
|
|
80
86
|
if (operand === '!=') {
|
|
@@ -83,6 +89,17 @@ const processFilters = (filters, conditions, queryParams, paramIndex) => {
|
|
|
83
89
|
conditions.push(\`\${field} IN (\${placeholders.join(', ')})\`)
|
|
84
90
|
}
|
|
85
91
|
} else {
|
|
92
|
+
if (operand === 'array_overlap') {
|
|
93
|
+
if (value === '' || value === null || value === undefined) return
|
|
94
|
+
// A single comma-joined string (the multi-select Category Filter's
|
|
95
|
+
// ?categoryFilter=a,b,c) expands to multiple ids; one id stays one.
|
|
96
|
+
const overlapValues = String(value).split(',').map((entry) => entry.trim()).filter(Boolean)
|
|
97
|
+
if (overlapValues.length === 0) return
|
|
98
|
+
conditions.push(\`jsonb_exists_any(NULLIF(\${field}, '')::jsonb, $\${paramIndex}::text[])\`)
|
|
99
|
+
queryParams.push(overlapValues)
|
|
100
|
+
paramIndex++
|
|
101
|
+
return
|
|
102
|
+
}
|
|
86
103
|
if (value === null) {
|
|
87
104
|
if (operand === '=') {
|
|
88
105
|
conditions.push(\`\${field} IS NULL\`)
|
package/src/fetchers/teleport.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { UIDLEcommerceCategory } from '@teleporthq/teleport-types'
|
|
1
2
|
import {
|
|
2
3
|
replaceSecretReference,
|
|
3
4
|
generateDateFormatterCode,
|
|
@@ -50,7 +51,8 @@ export const validateTeleportConfig = (
|
|
|
50
51
|
|
|
51
52
|
export const generateTeleportFetcher = (
|
|
52
53
|
config: Record<string, unknown>,
|
|
53
|
-
tableName: string
|
|
54
|
+
tableName: string,
|
|
55
|
+
categories?: UIDLEcommerceCategory[]
|
|
54
56
|
): string => {
|
|
55
57
|
const dbConfig = config as TeleportDBConfig
|
|
56
58
|
const schema = dbConfig.options?.schema
|
|
@@ -140,7 +142,7 @@ const getClient = () => {
|
|
|
140
142
|
${generateSafeJSONParseCode()}
|
|
141
143
|
|
|
142
144
|
${generateSearchEscapeHelpersCode()}
|
|
143
|
-
${getTransformationCode(tableName)}
|
|
145
|
+
${getTransformationCode(tableName, categories)}
|
|
144
146
|
${getTransformWrapperCode(tableName)}
|
|
145
147
|
const processFilters = (filters, conditions, queryParams, paramIndex) => {
|
|
146
148
|
if (!filters) return paramIndex
|
|
@@ -157,6 +159,15 @@ const processFilters = (filters, conditions, queryParams, paramIndex) => {
|
|
|
157
159
|
|
|
158
160
|
if (Array.isArray(value)) {
|
|
159
161
|
if (value.length === 0) return
|
|
162
|
+
if (operand === 'array_overlap') {
|
|
163
|
+
// Row column is a JSON array (e.g. category_ids). Match when it
|
|
164
|
+
// shares any element with the destination set. jsonb ?| (function
|
|
165
|
+
// form) avoids the '?' placeholder-token ambiguity some drivers hit.
|
|
166
|
+
conditions.push(\`jsonb_exists_any(NULLIF(\${field}, '')::jsonb, $\${paramIndex}::text[])\`)
|
|
167
|
+
queryParams.push(value.map((entry) => String(entry)))
|
|
168
|
+
paramIndex++
|
|
169
|
+
return
|
|
170
|
+
}
|
|
160
171
|
const placeholders = value.map(() => \`$\${paramIndex++}\`)
|
|
161
172
|
queryParams.push(...value)
|
|
162
173
|
if (operand === '!=') {
|
|
@@ -165,6 +176,17 @@ const processFilters = (filters, conditions, queryParams, paramIndex) => {
|
|
|
165
176
|
conditions.push(\`\${field} IN (\${placeholders.join(', ')})\`)
|
|
166
177
|
}
|
|
167
178
|
} else {
|
|
179
|
+
if (operand === 'array_overlap') {
|
|
180
|
+
if (value === '' || value === null || value === undefined) return
|
|
181
|
+
// A single comma-joined string (the multi-select Category Filter's
|
|
182
|
+
// ?categoryFilter=a,b,c) expands to multiple ids; one id stays one.
|
|
183
|
+
const overlapValues = String(value).split(',').map((entry) => entry.trim()).filter(Boolean)
|
|
184
|
+
if (overlapValues.length === 0) return
|
|
185
|
+
conditions.push(\`jsonb_exists_any(NULLIF(\${field}, '')::jsonb, $\${paramIndex}::text[])\`)
|
|
186
|
+
queryParams.push(overlapValues)
|
|
187
|
+
paramIndex++
|
|
188
|
+
return
|
|
189
|
+
}
|
|
168
190
|
if (value === null) {
|
|
169
191
|
if (operand === '=') {
|
|
170
192
|
conditions.push(\`\${field} IS NULL\`)
|
|
@@ -364,9 +386,22 @@ export default async function handler(req, res) {
|
|
|
364
386
|
: ''
|
|
365
387
|
}
|
|
366
388
|
|
|
389
|
+
// Stamp each row with a globally-correct 1-based \`__rowNumber\` (the page
|
|
390
|
+
// offset is applied server-side above), so list index columns keep counting
|
|
391
|
+
// across pages instead of restarting at 1. Renderer-internal field — it is
|
|
392
|
+
// filtered from ordinary field bindings and only read by the index column.
|
|
393
|
+
const __finalData = ${getTransformExpression(tableName) ? 'transformedData' : 'safeData'}
|
|
394
|
+
const __rowNumberStart = (typeof offsetValue === 'number' && !isNaN(offsetValue)) ? offsetValue : 0
|
|
395
|
+
const __numberedData = Array.isArray(__finalData)
|
|
396
|
+
? __finalData.map((__row, __i) =>
|
|
397
|
+
__row && typeof __row === 'object' && !Array.isArray(__row)
|
|
398
|
+
? Object.assign({}, __row, { __rowNumber: __rowNumberStart + __i + 1 })
|
|
399
|
+
: __row)
|
|
400
|
+
: __finalData
|
|
401
|
+
|
|
367
402
|
return res.status(200).json({
|
|
368
403
|
success: true,
|
|
369
|
-
data:
|
|
404
|
+
data: __numberedData,
|
|
370
405
|
timestamp: Date.now()
|
|
371
406
|
})
|
|
372
407
|
} catch (error) {
|
package/src/filter-utils.ts
CHANGED
|
@@ -12,27 +12,54 @@ const buildFilterEntry = (
|
|
|
12
12
|
types.objectProperty(types.identifier('operand'), types.stringLiteral(operand)),
|
|
13
13
|
])
|
|
14
14
|
|
|
15
|
-
// Predicate
|
|
15
|
+
// Predicate:
|
|
16
|
+
// (__f) => __f.destination !== '' && __f.destination !== null &&
|
|
17
|
+
// __f.destination !== undefined &&
|
|
18
|
+
// !(Array.isArray(__f.destination) && __f.destination.filter(Boolean).length === 0)
|
|
16
19
|
// Used at runtime to drop filter conditions whose destination resolves to an
|
|
17
20
|
// empty value. Keeps the page generic: state-bound filters (e.g.
|
|
18
21
|
// `selectedCategory === ''` after picking "All Categories") and url-bound
|
|
19
22
|
// filters (e.g. no `?categoryFilter=` in URL → `router?.query?.categoryFilter`
|
|
20
23
|
// is `undefined`) both fall away cleanly instead of being sent to the API as
|
|
21
24
|
// `destination: ''`, which the SQL backend interprets as a literal empty
|
|
22
|
-
// string and returns zero rows.
|
|
25
|
+
// string and returns zero rows. The array clause covers array-overlap filters
|
|
26
|
+
// (e.g. category `CATEGORY_DESCENDANTS[selectedCategory] || []`) whose "All"
|
|
27
|
+
// reset resolves to `[]` — an empty overlap set must mean "no filter", not
|
|
28
|
+
// "match nothing".
|
|
23
29
|
const buildNonEmptyDestinationPredicate = (): types.ArrowFunctionExpression => {
|
|
24
30
|
const f = types.identifier('__f')
|
|
25
31
|
const dest = types.memberExpression(f, types.identifier('destination'))
|
|
32
|
+
const isEmptyArray = types.logicalExpression(
|
|
33
|
+
'&&',
|
|
34
|
+
types.callExpression(
|
|
35
|
+
types.memberExpression(types.identifier('Array'), types.identifier('isArray')),
|
|
36
|
+
[dest]
|
|
37
|
+
),
|
|
38
|
+
types.binaryExpression(
|
|
39
|
+
'===',
|
|
40
|
+
types.memberExpression(
|
|
41
|
+
types.callExpression(types.memberExpression(dest, types.identifier('filter')), [
|
|
42
|
+
types.identifier('Boolean'),
|
|
43
|
+
]),
|
|
44
|
+
types.identifier('length')
|
|
45
|
+
),
|
|
46
|
+
types.numericLiteral(0)
|
|
47
|
+
)
|
|
48
|
+
)
|
|
26
49
|
return types.arrowFunctionExpression(
|
|
27
50
|
[f],
|
|
28
51
|
types.logicalExpression(
|
|
29
52
|
'&&',
|
|
30
53
|
types.logicalExpression(
|
|
31
54
|
'&&',
|
|
32
|
-
types.
|
|
33
|
-
|
|
55
|
+
types.logicalExpression(
|
|
56
|
+
'&&',
|
|
57
|
+
types.binaryExpression('!==', dest, types.stringLiteral('')),
|
|
58
|
+
types.binaryExpression('!==', dest, types.nullLiteral())
|
|
59
|
+
),
|
|
60
|
+
types.binaryExpression('!==', dest, types.identifier('undefined'))
|
|
34
61
|
),
|
|
35
|
-
types.
|
|
62
|
+
types.unaryExpression('!', isEmptyArray)
|
|
36
63
|
)
|
|
37
64
|
)
|
|
38
65
|
}
|
package/src/index.ts
CHANGED
|
@@ -606,7 +606,8 @@ export const createNextPagesDataSourcePlugin: ComponentPluginFactory<{}> = () =>
|
|
|
606
606
|
options.extractedResources,
|
|
607
607
|
dependencies,
|
|
608
608
|
dynamicRouteAttr,
|
|
609
|
-
uidl.outputOptions?.folderPath
|
|
609
|
+
uidl.outputOptions?.folderPath,
|
|
610
|
+
options.ecommerceSettings?.categories
|
|
610
611
|
)
|
|
611
612
|
|
|
612
613
|
if (result.success && result.chunk) {
|
|
@@ -643,7 +644,8 @@ export const createNextPagesDataSourcePlugin: ComponentPluginFactory<{}> = () =>
|
|
|
643
644
|
dataSourceNode,
|
|
644
645
|
dataSources,
|
|
645
646
|
componentChunk,
|
|
646
|
-
options.extractedResources
|
|
647
|
+
options.extractedResources,
|
|
648
|
+
options.ecommerceSettings?.categories
|
|
647
649
|
)
|
|
648
650
|
}
|
|
649
651
|
})
|
|
@@ -1253,7 +1255,8 @@ export const createNextComponentDataSourcePlugin: ComponentPluginFactory<{}> = (
|
|
|
1253
1255
|
dataSourceNode,
|
|
1254
1256
|
dataSources,
|
|
1255
1257
|
componentChunk,
|
|
1256
|
-
options.extractedResources
|
|
1258
|
+
options.extractedResources,
|
|
1259
|
+
options.ecommerceSettings?.categories
|
|
1257
1260
|
)
|
|
1258
1261
|
})
|
|
1259
1262
|
|
|
@@ -1337,7 +1340,9 @@ export const createNextComponentDataSourcePlugin: ComponentPluginFactory<{}> = (
|
|
|
1337
1340
|
try {
|
|
1338
1341
|
const fetcherCode = generateDataSourceFetcherWithCore(
|
|
1339
1342
|
dataSource,
|
|
1340
|
-
firstDataSourceInfo.tableName
|
|
1343
|
+
firstDataSourceInfo.tableName,
|
|
1344
|
+
false,
|
|
1345
|
+
options.ecommerceSettings?.categories
|
|
1341
1346
|
)
|
|
1342
1347
|
options.extractedResources[`utils/${fileName}`] = {
|
|
1343
1348
|
fileName,
|
package/src/pagination-plugin.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
ComponentPluginFactory,
|
|
4
4
|
ChunkType,
|
|
5
5
|
FileType,
|
|
6
|
+
UIDLEcommerceCategory,
|
|
6
7
|
} from '@teleporthq/teleport-types'
|
|
7
8
|
import * as types from '@babel/types'
|
|
8
9
|
import { parseExpression } from '@babel/parser'
|
|
@@ -642,7 +643,6 @@ function getStateVarsForUsage(usage: DataSourceUsage): {
|
|
|
642
643
|
combinedStateVar: string
|
|
643
644
|
setCombinedStateVar: string
|
|
644
645
|
skipDebounceRefVar: string
|
|
645
|
-
skipCountFetchRefVar: string
|
|
646
646
|
propsPrefix: string
|
|
647
647
|
} {
|
|
648
648
|
const idx = usage.index
|
|
@@ -659,7 +659,6 @@ function getStateVarsForUsage(usage: DataSourceUsage): {
|
|
|
659
659
|
combinedStateVar: `ds_${idx}_state`,
|
|
660
660
|
setCombinedStateVar: `setDs_${idx}_state`,
|
|
661
661
|
skipDebounceRefVar: `ds_${idx}_skipDebounce`,
|
|
662
|
-
skipCountFetchRefVar: `ds_${idx}_skipCountFetch`,
|
|
663
662
|
propsPrefix: `${usage.dataSourceIdentifier}_ds_${idx}`,
|
|
664
663
|
}
|
|
665
664
|
}
|
|
@@ -843,19 +842,6 @@ export const createNextArrayMapperPaginationPlugin: ComponentPluginFactory<{}> =
|
|
|
843
842
|
])
|
|
844
843
|
)
|
|
845
844
|
|
|
846
|
-
// Only add skipCountFetchRef for pages (where we have server-side count)
|
|
847
|
-
// For components, we need to fetch count on mount
|
|
848
|
-
if (isPage) {
|
|
849
|
-
stateDeclarations.push(
|
|
850
|
-
types.variableDeclaration('const', [
|
|
851
|
-
types.variableDeclarator(
|
|
852
|
-
types.identifier(vars.skipCountFetchRefVar),
|
|
853
|
-
types.callExpression(types.identifier('useRef'), [types.booleanLiteral(true)])
|
|
854
|
-
),
|
|
855
|
-
])
|
|
856
|
-
)
|
|
857
|
-
}
|
|
858
|
-
|
|
859
845
|
// maxPages state
|
|
860
846
|
const maxPagesInit = isPage
|
|
861
847
|
? types.logicalExpression(
|
|
@@ -1049,30 +1035,14 @@ export const createNextArrayMapperPaginationPlugin: ComponentPluginFactory<{}> =
|
|
|
1049
1035
|
// Build the count fetch effect body
|
|
1050
1036
|
const countFetchEffectBody: types.Statement[] = []
|
|
1051
1037
|
|
|
1052
|
-
//
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
types.blockStatement([
|
|
1061
|
-
types.expressionStatement(
|
|
1062
|
-
types.assignmentExpression(
|
|
1063
|
-
'=',
|
|
1064
|
-
types.memberExpression(
|
|
1065
|
-
types.identifier(vars.skipCountFetchRefVar),
|
|
1066
|
-
types.identifier('current')
|
|
1067
|
-
),
|
|
1068
|
-
types.booleanLiteral(false)
|
|
1069
|
-
)
|
|
1070
|
-
),
|
|
1071
|
-
types.returnStatement(),
|
|
1072
|
-
])
|
|
1073
|
-
)
|
|
1074
|
-
)
|
|
1075
|
-
}
|
|
1038
|
+
// Refresh the count on mount (no skip-on-mount guard). Pages seed maxPages
|
|
1039
|
+
// from the build-time `getStaticProps` count, but that snapshot goes stale:
|
|
1040
|
+
// rows added AFTER the build (e.g. the normalized product_variants table,
|
|
1041
|
+
// which is seeded/grows past one page during store generation) are not
|
|
1042
|
+
// reflected, so a frozen maxPages of 0/1 leaves "Next" permanently disabled
|
|
1043
|
+
// on data-heavy tables. Re-fetching the live count on mount corrects
|
|
1044
|
+
// maxPages so pagination tracks the real row count. The effect still runs
|
|
1045
|
+
// when the search query or a filter changes (see deps below).
|
|
1076
1046
|
|
|
1077
1047
|
// Add the fetch call
|
|
1078
1048
|
countFetchEffectBody.push(
|
|
@@ -1568,7 +1538,12 @@ export const createNextArrayMapperPaginationPlugin: ComponentPluginFactory<{}> =
|
|
|
1568
1538
|
}
|
|
1569
1539
|
|
|
1570
1540
|
// Create API route for all categories (including 'plain' for components)
|
|
1571
|
-
ensureAPIRouteExists(
|
|
1541
|
+
ensureAPIRouteExists(
|
|
1542
|
+
options.extractedResources,
|
|
1543
|
+
usage,
|
|
1544
|
+
options.dataSources,
|
|
1545
|
+
options.ecommerceSettings?.categories
|
|
1546
|
+
)
|
|
1572
1547
|
})
|
|
1573
1548
|
|
|
1574
1549
|
// STEP 3.5: Handle DataProviders WITHOUT repeaters (data-source-item type)
|
|
@@ -2700,7 +2675,8 @@ function wirePaginationButtons(
|
|
|
2700
2675
|
function ensureAPIRouteExists(
|
|
2701
2676
|
extractedResources: any,
|
|
2702
2677
|
usage: DataSourceUsage,
|
|
2703
|
-
dataSources: Record<string, any
|
|
2678
|
+
dataSources: Record<string, any>,
|
|
2679
|
+
categories?: UIDLEcommerceCategory[]
|
|
2704
2680
|
): void {
|
|
2705
2681
|
// Generate file name for the API route
|
|
2706
2682
|
const fileName = generateSafeFileName(
|
|
@@ -2718,7 +2694,9 @@ function ensureAPIRouteExists(
|
|
|
2718
2694
|
// Generate the utils file with fetchData, fetchCount, handler, and getCount
|
|
2719
2695
|
const fetcherCode = generateDataSourceFetcherWithCore(
|
|
2720
2696
|
dataSource,
|
|
2721
|
-
usage.resourceDefinition.tableName || 'data'
|
|
2697
|
+
usage.resourceDefinition.tableName || 'data',
|
|
2698
|
+
false,
|
|
2699
|
+
categories
|
|
2722
2700
|
)
|
|
2723
2701
|
|
|
2724
2702
|
extractedResources[`utils/${fileName}`] = {
|