@teleporthq/teleport-plugin-next-data-source 0.42.0 → 0.42.3

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.
Files changed (61) hide show
  1. package/COUNT_API_FIX.md +185 -0
  2. package/SEARCH_FIX_SUMMARY.md +96 -0
  3. package/dist/cjs/count-fetchers.d.ts.map +1 -1
  4. package/dist/cjs/count-fetchers.js +1 -1
  5. package/dist/cjs/count-fetchers.js.map +1 -1
  6. package/dist/cjs/fetchers/clickhouse.d.ts.map +1 -1
  7. package/dist/cjs/fetchers/clickhouse.js +1 -1
  8. package/dist/cjs/fetchers/clickhouse.js.map +1 -1
  9. package/dist/cjs/fetchers/firestore.d.ts.map +1 -1
  10. package/dist/cjs/fetchers/firestore.js +1 -1
  11. package/dist/cjs/fetchers/firestore.js.map +1 -1
  12. package/dist/cjs/fetchers/javascript.d.ts.map +1 -1
  13. package/dist/cjs/fetchers/javascript.js +1 -1
  14. package/dist/cjs/fetchers/javascript.js.map +1 -1
  15. package/dist/cjs/fetchers/redshift.d.ts.map +1 -1
  16. package/dist/cjs/fetchers/redshift.js +3 -1
  17. package/dist/cjs/fetchers/redshift.js.map +1 -1
  18. package/dist/cjs/fetchers/rest-api.d.ts.map +1 -1
  19. package/dist/cjs/fetchers/rest-api.js +2 -2
  20. package/dist/cjs/fetchers/rest-api.js.map +1 -1
  21. package/dist/cjs/fetchers/turso.d.ts.map +1 -1
  22. package/dist/cjs/fetchers/turso.js +1 -1
  23. package/dist/cjs/fetchers/turso.js.map +1 -1
  24. package/dist/cjs/pagination-plugin.d.ts.map +1 -1
  25. package/dist/cjs/pagination-plugin.js +280 -165
  26. package/dist/cjs/pagination-plugin.js.map +1 -1
  27. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  28. package/dist/esm/count-fetchers.d.ts.map +1 -1
  29. package/dist/esm/count-fetchers.js +1 -1
  30. package/dist/esm/count-fetchers.js.map +1 -1
  31. package/dist/esm/fetchers/clickhouse.d.ts.map +1 -1
  32. package/dist/esm/fetchers/clickhouse.js +1 -1
  33. package/dist/esm/fetchers/clickhouse.js.map +1 -1
  34. package/dist/esm/fetchers/firestore.d.ts.map +1 -1
  35. package/dist/esm/fetchers/firestore.js +1 -1
  36. package/dist/esm/fetchers/firestore.js.map +1 -1
  37. package/dist/esm/fetchers/javascript.d.ts.map +1 -1
  38. package/dist/esm/fetchers/javascript.js +1 -1
  39. package/dist/esm/fetchers/javascript.js.map +1 -1
  40. package/dist/esm/fetchers/redshift.d.ts.map +1 -1
  41. package/dist/esm/fetchers/redshift.js +3 -1
  42. package/dist/esm/fetchers/redshift.js.map +1 -1
  43. package/dist/esm/fetchers/rest-api.d.ts.map +1 -1
  44. package/dist/esm/fetchers/rest-api.js +2 -2
  45. package/dist/esm/fetchers/rest-api.js.map +1 -1
  46. package/dist/esm/fetchers/turso.d.ts.map +1 -1
  47. package/dist/esm/fetchers/turso.js +1 -1
  48. package/dist/esm/fetchers/turso.js.map +1 -1
  49. package/dist/esm/pagination-plugin.d.ts.map +1 -1
  50. package/dist/esm/pagination-plugin.js +280 -165
  51. package/dist/esm/pagination-plugin.js.map +1 -1
  52. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  53. package/package.json +2 -2
  54. package/src/count-fetchers.ts +2 -1
  55. package/src/fetchers/clickhouse.ts +12 -6
  56. package/src/fetchers/firestore.ts +45 -13
  57. package/src/fetchers/javascript.ts +48 -13
  58. package/src/fetchers/redshift.ts +32 -9
  59. package/src/fetchers/rest-api.ts +68 -6
  60. package/src/fetchers/turso.ts +46 -16
  61. package/src/pagination-plugin.ts +440 -296
@@ -49,7 +49,7 @@ import { generatePaginationLogic } from './array-mapper-pagination';
49
49
  import { extractDataSourceIntoNextAPIFolder } from './utils';
50
50
  export var createNextArrayMapperPaginationPlugin = function () {
51
51
  var paginationPlugin = function (structure) { return __awaiter(void 0, void 0, void 0, function () {
52
- var uidl, chunks, dependencies, options, componentChunk, variableDeclaration, declarator, arrowFunction, blockStatement, _a, paginatedMappers, searchOnlyMappers, paginationOnlyMappers, detectedPaginations, detectedSearchOnly, paginationInfos, getStaticPropsChunk, isPage, isComponent, opts, perPageMap, searchConfigMap, queryColumnsMap, hasSearchEnabled, firstReturnIndex, insertIndex, dataSourceToInfos_1, searchOnlyDataSources;
52
+ var uidl, chunks, dependencies, options, componentChunk, variableDeclaration, declarator, arrowFunction, blockStatement, _a, paginatedMappers, searchOnlyMappers, paginationOnlyMappers, detectedPaginations, detectedSearchOnly, paginationInfos, getStaticPropsChunk, isPage, isComponent, opts, perPageMap, searchConfigMap, queryColumnsMap, stateDeclarations, hasSearchEnabled, firstReturnIndex, insertIndex, dataSourceToInfos_1, componentUseEffects_1, componentReturnIndex, componentEffectsInsertIndex_1, searchOnlyDataSources;
53
53
  var _b, _c, _d;
54
54
  return __generator(this, function (_e) {
55
55
  uidl = structure.uidl, chunks = structure.chunks, dependencies = structure.dependencies, options = structure.options;
@@ -133,6 +133,7 @@ export var createNextArrayMapperPaginationPlugin = function () {
133
133
  perPageMap = ((_b = opts.paginationConfig) === null || _b === void 0 ? void 0 : _b.perPageMap) || new Map();
134
134
  searchConfigMap = ((_c = opts.paginationConfig) === null || _c === void 0 ? void 0 : _c.searchConfigMap) || new Map();
135
135
  queryColumnsMap = ((_d = opts.paginationConfig) === null || _d === void 0 ? void 0 : _d.queryColumnsMap) || new Map();
136
+ stateDeclarations = [];
136
137
  detectedPaginations.forEach(function (detected, index) {
137
138
  var paginationNodeId = "pg_".concat(index);
138
139
  // Use arrayMapperRenderProp if available, otherwise fall back to dataSourceIdentifier
@@ -143,6 +144,37 @@ export var createNextArrayMapperPaginationPlugin = function () {
143
144
  var queryColumns = queryColumnsMap.get(detected.dataSourceIdentifier);
144
145
  var info = generatePaginationLogic(paginationNodeId, detected.dataSourceIdentifier, perPage, searchConfig, queryColumns);
145
146
  paginationInfos.push(info);
147
+ // Add refs to track first render for each useEffect (add first)
148
+ if (info.searchEnabled) {
149
+ var skipCountFetchOnMountRefVar = "skipCountFetchOnMount_pg_".concat(index);
150
+ var skipCountFetchRefAST = types.variableDeclaration('const', [
151
+ types.variableDeclarator(types.identifier(skipCountFetchOnMountRefVar), types.callExpression(types.identifier('useRef'), [types.booleanLiteral(true)])),
152
+ ]);
153
+ stateDeclarations.push(skipCountFetchRefAST);
154
+ info.skipCountFetchOnMountRefVar = skipCountFetchOnMountRefVar;
155
+ var skipDebounceOnMountRefVar = "skipDebounceOnMount_pg_".concat(index);
156
+ var skipDebounceRefAST = types.variableDeclaration('const', [
157
+ types.variableDeclarator(types.identifier(skipDebounceOnMountRefVar), types.callExpression(types.identifier('useRef'), [types.booleanLiteral(true)])),
158
+ ]);
159
+ stateDeclarations.push(skipDebounceRefAST);
160
+ info.skipDebounceOnMountRefVar = skipDebounceOnMountRefVar;
161
+ }
162
+ // Add maxPages state
163
+ var maxPagesStateVar = "".concat(info.pageStateVar.replace('_page', ''), "_maxPages");
164
+ var setMaxPagesStateVar = "set".concat(maxPagesStateVar.charAt(0).toUpperCase() + maxPagesStateVar.slice(1));
165
+ // For pages: initialize from props (with pagination-specific prop name), for components: initialize to 0
166
+ var maxPagesInitValue = isPage
167
+ ? types.logicalExpression('||', types.optionalMemberExpression(types.identifier('props'), types.identifier("".concat(info.dataSourceIdentifier, "_pg_").concat(index, "_maxPages")), false, true), types.numericLiteral(0))
168
+ : types.numericLiteral(0);
169
+ var maxPagesStateAST = types.variableDeclaration('const', [
170
+ types.variableDeclarator(types.arrayPattern([
171
+ types.identifier(maxPagesStateVar),
172
+ types.identifier(setMaxPagesStateVar),
173
+ ]), types.callExpression(types.identifier('useState'), [maxPagesInitValue])),
174
+ ]);
175
+ stateDeclarations.push(maxPagesStateAST);
176
+ info.maxPagesStateVar = maxPagesStateVar;
177
+ info.setMaxPagesStateVar = setMaxPagesStateVar;
146
178
  // If both pagination and search are enabled, combine them into a single state object
147
179
  if (info.searchEnabled && info.searchQueryVar && info.setSearchQueryVar) {
148
180
  // Combined state: { page: 1, debouncedQuery: '' }
@@ -159,7 +191,7 @@ export var createNextArrayMapperPaginationPlugin = function () {
159
191
  ]),
160
192
  ])),
161
193
  ]);
162
- blockStatement.body.unshift(combinedStateAST);
194
+ stateDeclarations.push(combinedStateAST);
163
195
  // Still need the immediate search query state for the input
164
196
  var searchStateAST = types.variableDeclaration('const', [
165
197
  types.variableDeclarator(types.arrayPattern([
@@ -167,7 +199,7 @@ export var createNextArrayMapperPaginationPlugin = function () {
167
199
  types.identifier(info.setSearchQueryVar),
168
200
  ]), types.callExpression(types.identifier('useState'), [types.stringLiteral('')])),
169
201
  ]);
170
- blockStatement.body.unshift(searchStateAST);
202
+ stateDeclarations.push(searchStateAST);
171
203
  info.combinedStateVar = combinedStateVar;
172
204
  info.setCombinedStateVar = setCombinedStateVar;
173
205
  }
@@ -179,40 +211,13 @@ export var createNextArrayMapperPaginationPlugin = function () {
179
211
  types.identifier(info.setPageStateVar),
180
212
  ]), types.callExpression(types.identifier('useState'), [types.numericLiteral(1)])),
181
213
  ]);
182
- blockStatement.body.unshift(pageStateAST);
183
- }
184
- // Add maxPages state
185
- var maxPagesStateVar = "".concat(info.pageStateVar.replace('_page', ''), "_maxPages");
186
- var setMaxPagesStateVar = "set".concat(maxPagesStateVar.charAt(0).toUpperCase() + maxPagesStateVar.slice(1));
187
- // For pages: initialize from props (with pagination-specific prop name), for components: initialize to 0
188
- var maxPagesInitValue = isPage
189
- ? types.logicalExpression('||', types.optionalMemberExpression(types.identifier('props'), types.identifier("".concat(info.dataSourceIdentifier, "_pg_").concat(index, "_maxPages")), false, true), types.numericLiteral(0))
190
- : types.numericLiteral(0);
191
- var maxPagesStateAST = types.variableDeclaration('const', [
192
- types.variableDeclarator(types.arrayPattern([
193
- types.identifier(maxPagesStateVar),
194
- types.identifier(setMaxPagesStateVar),
195
- ]), types.callExpression(types.identifier('useState'), [maxPagesInitValue])),
196
- ]);
197
- blockStatement.body.unshift(maxPagesStateAST);
198
- info.maxPagesStateVar = maxPagesStateVar;
199
- info.setMaxPagesStateVar = setMaxPagesStateVar;
200
- // Add refs to track first render for each useEffect
201
- if (info.searchEnabled) {
202
- var skipDebounceOnMountRefVar = "skipDebounceOnMount_pg_".concat(index);
203
- var skipDebounceRefAST = types.variableDeclaration('const', [
204
- types.variableDeclarator(types.identifier(skipDebounceOnMountRefVar), types.callExpression(types.identifier('useRef'), [types.booleanLiteral(true)])),
205
- ]);
206
- blockStatement.body.unshift(skipDebounceRefAST);
207
- info.skipDebounceOnMountRefVar = skipDebounceOnMountRefVar;
208
- var skipCountFetchOnMountRefVar = "skipCountFetchOnMount_pg_".concat(index);
209
- var skipCountFetchRefAST = types.variableDeclaration('const', [
210
- types.variableDeclarator(types.identifier(skipCountFetchOnMountRefVar), types.callExpression(types.identifier('useRef'), [types.booleanLiteral(true)])),
211
- ]);
212
- blockStatement.body.unshift(skipCountFetchRefAST);
213
- info.skipCountFetchOnMountRefVar = skipCountFetchOnMountRefVar;
214
+ stateDeclarations.push(pageStateAST);
214
215
  }
215
216
  });
217
+ // Add all state declarations at once to the beginning in correct order
218
+ stateDeclarations.reverse().forEach(function (stateDecl) {
219
+ blockStatement.body.unshift(stateDecl);
220
+ });
216
221
  hasSearchEnabled = paginationInfos.some(function (info) { return info.searchEnabled; });
217
222
  if (hasSearchEnabled && !dependencies.useEffect) {
218
223
  dependencies.useEffect = {
@@ -262,74 +267,75 @@ export var createNextArrayMapperPaginationPlugin = function () {
262
267
  ]));
263
268
  blockStatement.body.splice(insertIndex, 0, debounceEffect);
264
269
  // Add useEffect to refetch count when search changes (for both pages and components)
265
- if (info.queryColumns && info.queryColumns.length > 0) {
266
- var detected = detectedPaginations.find(function (d) { return d.dataSourceIdentifier === info.dataSourceIdentifier; });
267
- if (!detected) {
268
- return;
269
- }
270
- var resourceDefAttr = detected.dataProviderJSX.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'resourceDefinition'; });
271
- if (resourceDefAttr &&
272
- resourceDefAttr.value &&
273
- resourceDefAttr.value.type === 'JSXExpressionContainer') {
274
- var resourceDef = resourceDefAttr.value.expression;
275
- if (resourceDef.type === 'ObjectExpression') {
276
- var dataSourceIdProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'dataSourceId'; });
277
- var tableNameProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'tableName'; });
278
- var dataSourceTypeProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'dataSourceType'; });
279
- if (dataSourceIdProp && tableNameProp && dataSourceTypeProp) {
280
- var dataSourceId = dataSourceIdProp.value.value;
281
- var tableName = tableNameProp.value.value;
282
- var dataSourceType = dataSourceTypeProp.value.value;
283
- var fileName = "".concat(dataSourceType, "-").concat(tableName, "-").concat(dataSourceId.substring(0, 8));
284
- var setMaxPagesStateVar = info.setMaxPagesStateVar;
285
- // Create useEffect to refetch count when debounced search changes
286
- var skipCountFetchOnMountRefVar = info.skipCountFetchOnMountRefVar;
287
- var combinedStateVar = info.combinedStateVar;
288
- var refetchCountEffect = types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
289
- types.arrowFunctionExpression([], types.blockStatement([
290
- types.ifStatement(types.memberExpression(types.identifier(skipCountFetchOnMountRefVar), types.identifier('current')), types.blockStatement([
291
- types.expressionStatement(types.assignmentExpression('=', types.memberExpression(types.identifier(skipCountFetchOnMountRefVar), types.identifier('current')), types.booleanLiteral(false))),
292
- types.returnStatement(),
293
- ])),
294
- types.expressionStatement(types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.callExpression(types.identifier('fetch'), [
295
- types.templateLiteral([
296
- types.templateElement({
297
- raw: "/api/".concat(fileName, "-count?"),
298
- cooked: "/api/".concat(fileName, "-count?"),
299
- }),
300
- types.templateElement({ raw: '', cooked: '' }),
301
- ], [
302
- types.newExpression(types.identifier('URLSearchParams'), [
303
- types.objectExpression([
304
- types.objectProperty(types.identifier('query'), types.memberExpression(types.identifier(combinedStateVar), types.identifier('debouncedQuery'))),
305
- types.objectProperty(types.identifier('queryColumns'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [
306
- types.arrayExpression(info.queryColumns.map(function (col) {
307
- return types.stringLiteral(col);
308
- })),
309
- ])),
310
- ]),
311
- ]),
270
+ var detected = detectedPaginations.find(function (d) { return d.dataSourceIdentifier === info.dataSourceIdentifier; });
271
+ if (!detected) {
272
+ return;
273
+ }
274
+ var resourceDefAttr = detected.dataProviderJSX.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'resourceDefinition'; });
275
+ if (resourceDefAttr &&
276
+ resourceDefAttr.value &&
277
+ resourceDefAttr.value.type === 'JSXExpressionContainer') {
278
+ var resourceDef = resourceDefAttr.value.expression;
279
+ if (resourceDef.type === 'ObjectExpression') {
280
+ var dataSourceIdProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'dataSourceId'; });
281
+ var tableNameProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'tableName'; });
282
+ var dataSourceTypeProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'dataSourceType'; });
283
+ if (dataSourceIdProp && tableNameProp && dataSourceTypeProp) {
284
+ var dataSourceId = dataSourceIdProp.value.value;
285
+ var tableName = tableNameProp.value.value;
286
+ var dataSourceType = dataSourceTypeProp.value.value;
287
+ var fileName = "".concat(dataSourceType, "-").concat(tableName, "-").concat(dataSourceId.substring(0, 8));
288
+ var setMaxPagesStateVar = info.setMaxPagesStateVar;
289
+ // Create useEffect to refetch count when debounced search changes
290
+ var skipCountFetchOnMountRefVar = info.skipCountFetchOnMountRefVar;
291
+ var combinedStateVar = info.combinedStateVar;
292
+ // Build URLSearchParams properties - query is always included, queryColumns is optional
293
+ var urlSearchParamsProperties = [
294
+ types.objectProperty(types.identifier('query'), types.memberExpression(types.identifier(combinedStateVar), types.identifier('debouncedQuery'))),
295
+ ];
296
+ // Add queryColumns only if they exist
297
+ if (info.queryColumns && info.queryColumns.length > 0) {
298
+ urlSearchParamsProperties.push(types.objectProperty(types.identifier('queryColumns'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [
299
+ types.arrayExpression(info.queryColumns.map(function (col) { return types.stringLiteral(col); })),
300
+ ])));
301
+ }
302
+ var refetchCountEffect = types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
303
+ types.arrowFunctionExpression([], types.blockStatement([
304
+ types.ifStatement(types.memberExpression(types.identifier(skipCountFetchOnMountRefVar), types.identifier('current')), types.blockStatement([
305
+ types.expressionStatement(types.assignmentExpression('=', types.memberExpression(types.identifier(skipCountFetchOnMountRefVar), types.identifier('current')), types.booleanLiteral(false))),
306
+ types.returnStatement(),
307
+ ])),
308
+ types.expressionStatement(types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.callExpression(types.identifier('fetch'), [
309
+ types.templateLiteral([
310
+ types.templateElement({
311
+ raw: "/api/".concat(fileName, "-count?"),
312
+ cooked: "/api/".concat(fileName, "-count?"),
313
+ }),
314
+ types.templateElement({ raw: '', cooked: '' }),
315
+ ], [
316
+ types.newExpression(types.identifier('URLSearchParams'), [
317
+ types.objectExpression(urlSearchParamsProperties),
312
318
  ]),
313
- ]), types.identifier('then')), [
314
- types.arrowFunctionExpression([types.identifier('res')], types.callExpression(types.memberExpression(types.identifier('res'), types.identifier('json')), [])),
315
- ]), types.identifier('then')), [
316
- types.arrowFunctionExpression([types.identifier('data')], types.blockStatement([
317
- types.ifStatement(types.logicalExpression('&&', types.identifier('data'), types.binaryExpression('in', types.stringLiteral('count'), types.identifier('data'))), types.blockStatement([
318
- types.expressionStatement(types.callExpression(types.identifier(setMaxPagesStateVar), [
319
- types.conditionalExpression(types.binaryExpression('===', types.memberExpression(types.identifier('data'), types.identifier('count')), types.numericLiteral(0)), types.numericLiteral(0), types.callExpression(types.memberExpression(types.identifier('Math'), types.identifier('ceil')), [
320
- types.binaryExpression('/', types.memberExpression(types.identifier('data'), types.identifier('count')), types.numericLiteral(info.perPage)),
321
- ])),
319
+ ]),
320
+ ]), types.identifier('then')), [
321
+ types.arrowFunctionExpression([types.identifier('res')], types.callExpression(types.memberExpression(types.identifier('res'), types.identifier('json')), [])),
322
+ ]), types.identifier('then')), [
323
+ types.arrowFunctionExpression([types.identifier('data')], types.blockStatement([
324
+ types.ifStatement(types.logicalExpression('&&', types.identifier('data'), types.binaryExpression('in', types.stringLiteral('count'), types.identifier('data'))), types.blockStatement([
325
+ types.expressionStatement(types.callExpression(types.identifier(setMaxPagesStateVar), [
326
+ types.conditionalExpression(types.binaryExpression('===', types.memberExpression(types.identifier('data'), types.identifier('count')), types.numericLiteral(0)), types.numericLiteral(0), types.callExpression(types.memberExpression(types.identifier('Math'), types.identifier('ceil')), [
327
+ types.binaryExpression('/', types.memberExpression(types.identifier('data'), types.identifier('count')), types.numericLiteral(info.perPage)),
322
328
  ])),
323
329
  ])),
324
330
  ])),
325
331
  ])),
326
332
  ])),
327
- types.arrayExpression([
328
- types.memberExpression(types.identifier(combinedStateVar), types.identifier('debouncedQuery')),
329
- ]),
330
- ]));
331
- blockStatement.body.splice(insertIndex, 0, refetchCountEffect);
332
- }
333
+ ])),
334
+ types.arrayExpression([
335
+ types.memberExpression(types.identifier(combinedStateVar), types.identifier('debouncedQuery')),
336
+ ]),
337
+ ]));
338
+ blockStatement.body.splice(insertIndex, 0, refetchCountEffect);
333
339
  }
334
340
  }
335
341
  }
@@ -379,7 +385,7 @@ export var createNextArrayMapperPaginationPlugin = function () {
379
385
  }
380
386
  dataSourceToInfos_1.get(info.dataSourceIdentifier).push({ info: info, detected: detected, fileName: fileName });
381
387
  });
382
- // Create ONE useEffect per unique data source
388
+ componentUseEffects_1 = [];
383
389
  dataSourceToInfos_1.forEach(function (infos) {
384
390
  var fileName = infos[0].fileName;
385
391
  // Create array of setState calls - one for each pagination using this data source
@@ -407,7 +413,13 @@ export var createNextArrayMapperPaginationPlugin = function () {
407
413
  ])),
408
414
  types.arrayExpression([]),
409
415
  ]));
410
- blockStatement.body.unshift(useEffectAST);
416
+ componentUseEffects_1.push(useEffectAST);
417
+ });
418
+ componentReturnIndex = blockStatement.body.findIndex(function (stmt) { return stmt.type === 'ReturnStatement'; });
419
+ componentEffectsInsertIndex_1 = componentReturnIndex !== -1 ? componentReturnIndex : blockStatement.body.length;
420
+ // Insert in reverse order to maintain correct order
421
+ componentUseEffects_1.reverse().forEach(function (effect) {
422
+ blockStatement.body.splice(componentEffectsInsertIndex_1, 0, effect);
411
423
  });
412
424
  }
413
425
  createAPIRoutesForPaginatedDataSources(uidl.node, options.dataSources, componentChunk, options.extractedResources, paginationInfos, isComponent);
@@ -421,7 +433,7 @@ export var createNextArrayMapperPaginationPlugin = function () {
421
433
  }
422
434
  searchOnlyDataSources = detectedSearchOnly;
423
435
  if (searchOnlyDataSources.length > 0) {
424
- handleSearchOnlyArrayMappers(blockStatement, searchOnlyDataSources, searchConfigMap, queryColumnsMap, insertIndex, dependencies);
436
+ handleSearchOnlyArrayMappers(blockStatement, searchOnlyDataSources, searchConfigMap, queryColumnsMap, dependencies);
425
437
  // Create API routes for search-only data sources
426
438
  createAPIRoutesForSearchOnlyDataSources(uidl.node, options.dataSources, componentChunk, options.extractedResources, searchOnlyDataSources);
427
439
  }
@@ -430,8 +442,66 @@ export var createNextArrayMapperPaginationPlugin = function () {
430
442
  }); };
431
443
  return paginationPlugin;
432
444
  };
445
+ function findParentNode(root, target, currentParent) {
446
+ if (currentParent === void 0) { currentParent = null; }
447
+ if (!root || !target) {
448
+ return null;
449
+ }
450
+ if (root === target) {
451
+ return currentParent;
452
+ }
453
+ if (root.type === 'JSXElement' || root.type === 'JSXFragment') {
454
+ if (root.children && Array.isArray(root.children)) {
455
+ for (var _i = 0, _a = root.children; _i < _a.length; _i++) {
456
+ var child = _a[_i];
457
+ var found = findParentNode(child, target, root);
458
+ if (found !== null) {
459
+ return found;
460
+ }
461
+ }
462
+ }
463
+ }
464
+ else if (root.type === 'JSXExpressionContainer') {
465
+ if (root.expression) {
466
+ var found = findParentNode(root.expression, target, root);
467
+ if (found !== null) {
468
+ return found;
469
+ }
470
+ }
471
+ }
472
+ else if (root.type === 'BlockStatement') {
473
+ if (root.body && Array.isArray(root.body)) {
474
+ for (var _b = 0, _c = root.body; _b < _c.length; _b++) {
475
+ var stmt = _c[_b];
476
+ var found = findParentNode(stmt, target, root);
477
+ if (found !== null) {
478
+ return found;
479
+ }
480
+ }
481
+ }
482
+ }
483
+ else if (root.type === 'ReturnStatement') {
484
+ if (root.argument) {
485
+ var found = findParentNode(root.argument, target, root);
486
+ if (found !== null) {
487
+ return found;
488
+ }
489
+ }
490
+ }
491
+ else if (root.type === 'ConditionalExpression') {
492
+ var foundConsequent = findParentNode(root.consequent, target, root);
493
+ if (foundConsequent !== null) {
494
+ return foundConsequent;
495
+ }
496
+ var foundAlternate = findParentNode(root.alternate, target, root);
497
+ if (foundAlternate !== null) {
498
+ return foundAlternate;
499
+ }
500
+ }
501
+ return null;
502
+ }
433
503
  function detectPaginationsAndSearchFromJSX(blockStatement, uidlNode) {
434
- var dataProviderMap = new Map();
504
+ var dataProviderList = [];
435
505
  var arrayMapperInfoMap = new Map();
436
506
  if (uidlNode) {
437
507
  var collectArrayMapperInfo_1 = function (node) {
@@ -597,32 +667,35 @@ function detectPaginationsAndSearchFromJSX(blockStatement, uidlNode) {
597
667
  var dataProviderIdentifier = nameAttr.value.expression.value;
598
668
  var paginationNodeInfo = null;
599
669
  var searchInputInfo = null;
600
- // Look through parent's children for siblings
601
- if (parent && parent.children && Array.isArray(parent.children)) {
602
- parent.children.forEach(function (sibling) {
670
+ var findSearchAndPaginationInScope = function (scopeNode, skipNode) {
671
+ if (skipNode === void 0) { skipNode = null; }
672
+ if (!scopeNode || !scopeNode.children || !Array.isArray(scopeNode.children)) {
673
+ return;
674
+ }
675
+ scopeNode.children.forEach(function (child) {
603
676
  var _a, _b, _c;
604
- if (sibling === dataProvider) {
677
+ if (child === skipNode) {
605
678
  return;
606
679
  }
607
- if (sibling.type === 'JSXElement') {
608
- var siblingClassName = getClassName(((_a = sibling.openingElement) === null || _a === void 0 ? void 0 : _a.attributes) || []);
609
- var siblingElementName = (_c = (_b = sibling.openingElement) === null || _b === void 0 ? void 0 : _b.name) === null || _c === void 0 ? void 0 : _c.name;
680
+ if (child.type === 'JSXElement') {
681
+ var childClassName = getClassName(((_a = child.openingElement) === null || _a === void 0 ? void 0 : _a.attributes) || []);
682
+ var childElementName = (_c = (_b = child.openingElement) === null || _b === void 0 ? void 0 : _b.name) === null || _c === void 0 ? void 0 : _c.name;
610
683
  // Found pagination node
611
- if (siblingClassName && siblingClassName.includes('cms-pagination-node')) {
612
- var prevClass = findChildWithClass(sibling, 'previous');
613
- var nextClass = findChildWithClass(sibling, 'next');
684
+ if (childClassName && childClassName.includes('cms-pagination-node')) {
685
+ var prevClass = findChildWithClass(child, 'previous');
686
+ var nextClass = findChildWithClass(child, 'next');
614
687
  if (prevClass || nextClass) {
615
688
  paginationNodeInfo = {
616
- class: siblingClassName,
689
+ class: childClassName,
617
690
  prevClass: prevClass,
618
691
  nextClass: nextClass,
619
692
  };
620
693
  }
621
694
  }
622
695
  // Found search container - search for input inside it
623
- if (siblingClassName && siblingClassName.includes('data-source-search-node')) {
624
- if (sibling.children && Array.isArray(sibling.children)) {
625
- sibling.children.forEach(function (searchChild) {
696
+ if (childClassName && childClassName.includes('data-source-search-node')) {
697
+ if (child.children && Array.isArray(child.children)) {
698
+ child.children.forEach(function (searchChild) {
626
699
  var _a, _b, _c;
627
700
  if (searchChild.type === 'JSXElement') {
628
701
  var searchChildElementName = (_b = (_a = searchChild.openingElement) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.name;
@@ -639,21 +712,32 @@ function detectPaginationsAndSearchFromJSX(blockStatement, uidlNode) {
639
712
  });
640
713
  }
641
714
  }
642
- // Also check if search input is a direct sibling
643
- if (siblingClassName &&
644
- siblingClassName.includes('search-input') &&
645
- siblingElementName === 'input') {
715
+ // Also check if search input is a direct child
716
+ if (childClassName &&
717
+ childClassName.includes('search-input') &&
718
+ childElementName === 'input') {
646
719
  searchInputInfo = {
647
- class: siblingClassName,
648
- jsx: sibling,
720
+ class: childClassName,
721
+ jsx: child,
649
722
  };
650
723
  }
724
+ if (!searchInputInfo || !paginationNodeInfo) {
725
+ findSearchAndPaginationInScope(child, skipNode);
726
+ }
651
727
  }
652
728
  });
729
+ };
730
+ var currentScope = parent;
731
+ var depth = 0;
732
+ var maxDepth = 5;
733
+ while (currentScope && (!searchInputInfo || !paginationNodeInfo) && depth < maxDepth) {
734
+ findSearchAndPaginationInScope(currentScope, depth === 0 ? dataProvider : null);
735
+ currentScope = findParentNode(blockStatement, currentScope);
736
+ depth++;
653
737
  }
654
738
  // Record the DataProvider with its pagination/search info
655
- var uniqueKey = "".concat(dataProviderIdentifier, "__").concat(arrayMapperRenderProp);
656
- dataProviderMap.set(uniqueKey, {
739
+ // Use array instead of Map to handle multiple DataProviders with same name
740
+ dataProviderList.push({
657
741
  identifier: dataProviderIdentifier,
658
742
  dataProvider: dataProvider,
659
743
  arrayMapperRenderProp: arrayMapperRenderProp,
@@ -668,9 +752,16 @@ function detectPaginationsAndSearchFromJSX(blockStatement, uidlNode) {
668
752
  var searchOnlyMappers = [];
669
753
  var paginationOnlyMappers = [];
670
754
  var plainMappers = [];
671
- dataProviderMap.forEach(function (info) {
755
+ dataProviderList.forEach(function (info) {
672
756
  var _a, _b, _c, _d;
673
- if (info.hasPagination && info.hasSearch) {
757
+ // Check UIDL flags for this array mapper
758
+ var uidlInfo = info.arrayMapperRenderProp
759
+ ? arrayMapperInfoMap.get(info.arrayMapperRenderProp)
760
+ : null;
761
+ // Only process pagination/search if UIDL explicitly enables it
762
+ var shouldHavePagination = (uidlInfo === null || uidlInfo === void 0 ? void 0 : uidlInfo.paginated) && info.hasPagination;
763
+ var shouldHaveSearch = (uidlInfo === null || uidlInfo === void 0 ? void 0 : uidlInfo.searchEnabled) && info.hasSearch;
764
+ if (shouldHavePagination && shouldHaveSearch) {
674
765
  // Pagination + Search
675
766
  paginatedMappers.push({
676
767
  paginationNodeClass: info.paginationNode.class,
@@ -683,7 +774,7 @@ function detectPaginationsAndSearchFromJSX(blockStatement, uidlNode) {
683
774
  searchInputJSX: (_b = info.searchInput) === null || _b === void 0 ? void 0 : _b.jsx,
684
775
  });
685
776
  }
686
- else if (info.hasPagination && !info.hasSearch) {
777
+ else if (shouldHavePagination && !shouldHaveSearch) {
687
778
  // Pagination only
688
779
  paginationOnlyMappers.push({
689
780
  paginationNodeClass: info.paginationNode.class,
@@ -696,7 +787,7 @@ function detectPaginationsAndSearchFromJSX(blockStatement, uidlNode) {
696
787
  searchInputJSX: undefined,
697
788
  });
698
789
  }
699
- else if (!info.hasPagination && info.hasSearch) {
790
+ else if (!shouldHavePagination && shouldHaveSearch) {
700
791
  // Search only
701
792
  searchOnlyMappers.push({
702
793
  paginationNodeClass: '',
@@ -710,7 +801,7 @@ function detectPaginationsAndSearchFromJSX(blockStatement, uidlNode) {
710
801
  });
711
802
  }
712
803
  else {
713
- // Plain (no pagination, no search)
804
+ // Plain (no pagination, no search) - UIDL doesn't enable it or no controls found
714
805
  plainMappers.push({
715
806
  paginationNodeClass: '',
716
807
  prevButtonClass: null,
@@ -725,7 +816,9 @@ function detectPaginationsAndSearchFromJSX(blockStatement, uidlNode) {
725
816
  });
726
817
  return { paginatedMappers: paginatedMappers, searchOnlyMappers: searchOnlyMappers, paginationOnlyMappers: paginationOnlyMappers, plainMappers: plainMappers };
727
818
  }
728
- function handleSearchOnlyArrayMappers(blockStatement, searchOnlyDataSources, searchConfigMap, queryColumnsMap, insertIndex, dependencies) {
819
+ function handleSearchOnlyArrayMappers(blockStatement, searchOnlyDataSources, searchConfigMap, queryColumnsMap, dependencies) {
820
+ var searchOnlyStates = [];
821
+ var searchOnlyEffects = [];
729
822
  searchOnlyDataSources.forEach(function (detected, index) {
730
823
  var searchId = "search_".concat(index);
731
824
  var searchQueryVar = "".concat(searchId, "_query");
@@ -736,11 +829,11 @@ function handleSearchOnlyArrayMappers(blockStatement, searchOnlyDataSources, sea
736
829
  var searchConfig = searchConfigMap.get(detected.dataSourceIdentifier);
737
830
  var searchDebounce = (searchConfig === null || searchConfig === void 0 ? void 0 : searchConfig.searchDebounce) || 300;
738
831
  var queryColumns = queryColumnsMap.get(detected.dataSourceIdentifier);
739
- // Add search query state
740
- var searchStateAST = types.variableDeclaration('const', [
741
- types.variableDeclarator(types.arrayPattern([types.identifier(searchQueryVar), types.identifier(setSearchQueryVar)]), types.callExpression(types.identifier('useState'), [types.stringLiteral('')])),
832
+ // Add skip ref
833
+ var skipRefAST = types.variableDeclaration('const', [
834
+ types.variableDeclarator(types.identifier(skipDebounceOnMountRefVar), types.callExpression(types.identifier('useRef'), [types.booleanLiteral(true)])),
742
835
  ]);
743
- blockStatement.body.unshift(searchStateAST);
836
+ searchOnlyStates.push(skipRefAST);
744
837
  // Add debounced search state
745
838
  var debouncedSearchStateAST = types.variableDeclaration('const', [
746
839
  types.variableDeclarator(types.arrayPattern([
@@ -748,12 +841,12 @@ function handleSearchOnlyArrayMappers(blockStatement, searchOnlyDataSources, sea
748
841
  types.identifier(setDebouncedSearchQueryVar),
749
842
  ]), types.callExpression(types.identifier('useState'), [types.stringLiteral('')])),
750
843
  ]);
751
- blockStatement.body.unshift(debouncedSearchStateAST);
752
- // Add skip ref
753
- var skipRefAST = types.variableDeclaration('const', [
754
- types.variableDeclarator(types.identifier(skipDebounceOnMountRefVar), types.callExpression(types.identifier('useRef'), [types.booleanLiteral(true)])),
844
+ searchOnlyStates.push(debouncedSearchStateAST);
845
+ // Add search query state
846
+ var searchStateAST = types.variableDeclaration('const', [
847
+ types.variableDeclarator(types.arrayPattern([types.identifier(searchQueryVar), types.identifier(setSearchQueryVar)]), types.callExpression(types.identifier('useState'), [types.stringLiteral('')])),
755
848
  ]);
756
- blockStatement.body.unshift(skipRefAST);
849
+ searchOnlyStates.push(searchStateAST);
757
850
  // Add useEffect for debouncing
758
851
  if (!dependencies.useEffect) {
759
852
  dependencies.useEffect = {
@@ -785,7 +878,7 @@ function handleSearchOnlyArrayMappers(blockStatement, searchOnlyDataSources, sea
785
878
  ])),
786
879
  types.arrayExpression([types.identifier(searchQueryVar)]),
787
880
  ]));
788
- blockStatement.body.splice(insertIndex, 0, debounceEffect);
881
+ searchOnlyEffects.push(debounceEffect);
789
882
  // Modify DataProvider to include search params (even without queryColumns)
790
883
  if (detected.dataProviderJSX) {
791
884
  addSearchParamsToDataProvider(detected.dataProviderJSX, {
@@ -802,6 +895,17 @@ function handleSearchOnlyArrayMappers(blockStatement, searchOnlyDataSources, sea
802
895
  });
803
896
  }
804
897
  });
898
+ // Add all state declarations at the beginning in correct order
899
+ searchOnlyStates.reverse().forEach(function (stateDecl) {
900
+ blockStatement.body.unshift(stateDecl);
901
+ });
902
+ // Recalculate insertIndex after adding states (since unshift shifted everything)
903
+ var newInsertIndex = blockStatement.body.findIndex(function (stmt) { return stmt.type === 'ReturnStatement'; });
904
+ var finalInsertIndex = newInsertIndex !== -1 ? newInsertIndex : blockStatement.body.length;
905
+ // Add all useEffect hooks before the return statement
906
+ searchOnlyEffects.reverse().forEach(function (effect) {
907
+ blockStatement.body.splice(finalInsertIndex, 0, effect);
908
+ });
805
909
  }
806
910
  function addSearchParamsToDataProvider(dataProviderJSX, config) {
807
911
  var _a, _b;
@@ -1036,6 +1140,7 @@ function findChildWithClass(node, classSubstring) {
1036
1140
  return null;
1037
1141
  }
1038
1142
  function modifyPaginationButtons(blockStatement, detectedPaginations, paginationInfos) {
1143
+ var modifiedButtons = new Set();
1039
1144
  var modifyNode = function (node) {
1040
1145
  if (!node) {
1041
1146
  return;
@@ -1043,20 +1148,25 @@ function modifyPaginationButtons(blockStatement, detectedPaginations, pagination
1043
1148
  if (node.type === 'JSXElement') {
1044
1149
  var openingElement = node.openingElement;
1045
1150
  if (openingElement && openingElement.name && openingElement.name.type === 'JSXIdentifier') {
1046
- var className_1 = getClassName(openingElement.attributes);
1047
- if (className_1) {
1048
- detectedPaginations.forEach(function (detected, index) {
1151
+ var className = getClassName(openingElement.attributes);
1152
+ if (className && !modifiedButtons.has(node)) {
1153
+ for (var index = 0; index < detectedPaginations.length; index++) {
1154
+ var detected = detectedPaginations[index];
1049
1155
  var info = paginationInfos[index];
1050
1156
  if (!info) {
1051
- return;
1157
+ continue;
1052
1158
  }
1053
- if (className_1 === detected.prevButtonClass) {
1159
+ if (className === detected.prevButtonClass) {
1054
1160
  convertToButton(node, info, 'prev');
1161
+ modifiedButtons.add(node);
1162
+ break;
1055
1163
  }
1056
- else if (className_1 === detected.nextButtonClass) {
1164
+ else if (className === detected.nextButtonClass) {
1057
1165
  convertToButton(node, info, 'next');
1166
+ modifiedButtons.add(node);
1167
+ break;
1058
1168
  }
1059
- });
1169
+ }
1060
1170
  }
1061
1171
  }
1062
1172
  }
@@ -1074,6 +1184,7 @@ function modifyPaginationButtons(blockStatement, detectedPaginations, pagination
1074
1184
  modifyNode(blockStatement);
1075
1185
  }
1076
1186
  function modifySearchInputs(blockStatement, detectedPaginations, paginationInfos) {
1187
+ var modifiedInputs = new Set();
1077
1188
  var modifyNode = function (node) {
1078
1189
  if (!node) {
1079
1190
  return;
@@ -1081,21 +1192,20 @@ function modifySearchInputs(blockStatement, detectedPaginations, paginationInfos
1081
1192
  if (node.type === 'JSXElement') {
1082
1193
  var openingElement = node.openingElement;
1083
1194
  if (openingElement && openingElement.name && openingElement.name.type === 'JSXIdentifier') {
1084
- var className_2 = getClassName(openingElement.attributes);
1085
- if (className_2) {
1086
- detectedPaginations.forEach(function (detected, index) {
1195
+ var className = getClassName(openingElement.attributes);
1196
+ if (className && !modifiedInputs.has(node)) {
1197
+ for (var index = 0; index < detectedPaginations.length; index++) {
1198
+ var detected = detectedPaginations[index];
1087
1199
  var info = paginationInfos[index];
1088
1200
  if (!info || !info.searchEnabled) {
1089
- return;
1201
+ continue;
1090
1202
  }
1091
- if (className_2 === detected.searchInputClass) {
1203
+ if (className === detected.searchInputClass) {
1092
1204
  addSearchInputHandlers(node, info);
1205
+ modifiedInputs.add(node);
1206
+ break;
1093
1207
  }
1094
- else if (className_2 && className_2.includes('search-input')) {
1095
- // Fallback: match any input with 'search-input' in class
1096
- addSearchInputHandlers(node, info);
1097
- }
1098
- });
1208
+ }
1099
1209
  }
1100
1210
  }
1101
1211
  }
@@ -1399,6 +1509,8 @@ function modifyGetStaticPropsForPagination(chunks, paginationInfos) {
1399
1509
  }
1400
1510
  function createAPIRoutesForPaginatedDataSources(uidlNode, dataSources, componentChunk, extractedResources, paginationInfos, isComponent) {
1401
1511
  var paginatedDataSourceIds = new Set(paginationInfos.map(function (info) { return info.dataSourceIdentifier; }));
1512
+ var searchEnabledDataSources = new Set(paginationInfos.filter(function (info) { return info.searchEnabled; }).map(function (info) { return info.dataSourceIdentifier; }));
1513
+ var createdCountRoutes = new Set();
1402
1514
  var traverseForDataSources = function (node) {
1403
1515
  var _a;
1404
1516
  if (!node) {
@@ -1408,8 +1520,9 @@ function createAPIRoutesForPaginatedDataSources(uidlNode, dataSources, component
1408
1520
  var renderProp = node.content.renderPropIdentifier;
1409
1521
  if (renderProp && paginatedDataSourceIds.has(renderProp)) {
1410
1522
  extractDataSourceIntoNextAPIFolder(node, dataSources, componentChunk, extractedResources);
1411
- // For components, also create count API route
1412
- if (isComponent) {
1523
+ var hasSearch = searchEnabledDataSources.has(renderProp);
1524
+ var needsCountRoute = isComponent || hasSearch;
1525
+ if (needsCountRoute) {
1413
1526
  var resourceDef = node.content.resourceDefinition;
1414
1527
  if (resourceDef) {
1415
1528
  var dataSourceId = resourceDef.dataSourceId;
@@ -1417,13 +1530,15 @@ function createAPIRoutesForPaginatedDataSources(uidlNode, dataSources, component
1417
1530
  var dataSourceType = resourceDef.dataSourceType;
1418
1531
  var fileName = "".concat(dataSourceType, "-").concat(tableName, "-").concat(dataSourceId.substring(0, 8));
1419
1532
  var countFileName = "".concat(fileName, "-count");
1420
- // Create count API route that exports getCount handler
1421
- extractedResources["api/".concat(countFileName)] = {
1422
- fileName: countFileName,
1423
- fileType: FileType.JS,
1424
- path: ['pages', 'api'],
1425
- content: "import dataSource from '../../utils/data-sources/".concat(fileName, "'\n\nexport default dataSource.getCount\n"),
1426
- };
1533
+ if (!createdCountRoutes.has(countFileName)) {
1534
+ extractedResources["api/".concat(countFileName)] = {
1535
+ fileName: countFileName,
1536
+ fileType: FileType.JS,
1537
+ path: ['pages', 'api'],
1538
+ content: "import dataSource from '../../utils/data-sources/".concat(fileName, "'\n\nexport default dataSource.getCount\n"),
1539
+ };
1540
+ createdCountRoutes.add(countFileName);
1541
+ }
1427
1542
  }
1428
1543
  }
1429
1544
  }