@teleporthq/teleport-plugin-next-data-source 0.42.4 → 0.42.6

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 (35) hide show
  1. package/dist/cjs/array-mapper-pagination.d.ts +5 -0
  2. package/dist/cjs/array-mapper-pagination.d.ts.map +1 -1
  3. package/dist/cjs/array-mapper-pagination.js.map +1 -1
  4. package/dist/cjs/array-mapper-registry.d.ts +84 -0
  5. package/dist/cjs/array-mapper-registry.d.ts.map +1 -0
  6. package/dist/cjs/array-mapper-registry.js +291 -0
  7. package/dist/cjs/array-mapper-registry.js.map +1 -0
  8. package/dist/cjs/index.d.ts.map +1 -1
  9. package/dist/cjs/index.js +36 -14
  10. package/dist/cjs/index.js.map +1 -1
  11. package/dist/cjs/pagination-plugin.d.ts +1 -3
  12. package/dist/cjs/pagination-plugin.d.ts.map +1 -1
  13. package/dist/cjs/pagination-plugin.js +908 -1351
  14. package/dist/cjs/pagination-plugin.js.map +1 -1
  15. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  16. package/dist/esm/array-mapper-pagination.d.ts +5 -0
  17. package/dist/esm/array-mapper-pagination.d.ts.map +1 -1
  18. package/dist/esm/array-mapper-pagination.js.map +1 -1
  19. package/dist/esm/array-mapper-registry.d.ts +84 -0
  20. package/dist/esm/array-mapper-registry.d.ts.map +1 -0
  21. package/dist/esm/array-mapper-registry.js +287 -0
  22. package/dist/esm/array-mapper-registry.js.map +1 -0
  23. package/dist/esm/index.d.ts.map +1 -1
  24. package/dist/esm/index.js +36 -14
  25. package/dist/esm/index.js.map +1 -1
  26. package/dist/esm/pagination-plugin.d.ts +1 -3
  27. package/dist/esm/pagination-plugin.d.ts.map +1 -1
  28. package/dist/esm/pagination-plugin.js +909 -1352
  29. package/dist/esm/pagination-plugin.js.map +1 -1
  30. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +2 -2
  32. package/src/array-mapper-pagination.ts +5 -0
  33. package/src/array-mapper-registry.ts +408 -0
  34. package/src/index.ts +24 -1
  35. package/src/pagination-plugin.ts +1860 -2132
@@ -58,26 +58,167 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
58
58
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
59
59
  }
60
60
  };
61
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
62
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
63
- if (ar || !(i in from)) {
64
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
65
- ar[i] = from[i];
66
- }
67
- }
68
- return to.concat(ar || Array.prototype.slice.call(from));
69
- };
70
61
  Object.defineProperty(exports, "__esModule", { value: true });
71
62
  exports.createNextArrayMapperPaginationPlugin = void 0;
72
63
  var teleport_types_1 = require("@teleporthq/teleport-types");
73
64
  var types = __importStar(require("@babel/types"));
74
- var array_mapper_pagination_1 = require("./array-mapper-pagination");
65
+ var teleport_shared_1 = require("@teleporthq/teleport-shared");
75
66
  var utils_1 = require("./utils");
67
+ // Scan UIDL to find all data source usages and build a registry
68
+ function buildStateRegistry(uidlNode) {
69
+ var usages = [];
70
+ var byDataSourceId = new Map();
71
+ var byArrayMapperRenderProp = new Map();
72
+ var index = 0;
73
+ var traverse = function (node, parentDataSource) {
74
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
75
+ if (!node || typeof node !== 'object') {
76
+ return;
77
+ }
78
+ // Found a data-source-list (DataProvider)
79
+ if (node.type === 'data-source-list' && ((_a = node.content) === null || _a === void 0 ? void 0 : _a.renderPropIdentifier)) {
80
+ var dsIdentifier = node.content.renderPropIdentifier;
81
+ var resourceDef = node.content.resourceDefinition || {};
82
+ var resourceParams = ((_b = node.content.resource) === null || _b === void 0 ? void 0 : _b.params) || {};
83
+ // Look for cms-list-repeater inside this data-source-list
84
+ var newParent = {
85
+ identifier: dsIdentifier,
86
+ resourceDef: resourceDef,
87
+ resourceParams: resourceParams,
88
+ };
89
+ // Traverse into success/error/loading nodes
90
+ if ((_c = node.content.nodes) === null || _c === void 0 ? void 0 : _c.success) {
91
+ traverse(node.content.nodes.success, newParent);
92
+ }
93
+ if ((_d = node.content.nodes) === null || _d === void 0 ? void 0 : _d.error) {
94
+ traverse(node.content.nodes.error, newParent);
95
+ }
96
+ if ((_e = node.content.nodes) === null || _e === void 0 ? void 0 : _e.loading) {
97
+ traverse(node.content.nodes.loading, newParent);
98
+ }
99
+ return;
100
+ }
101
+ // Found a cms-list-repeater (Repeater with pagination/search config)
102
+ var isCmsListRepeater = node.type === 'cms-list-repeater' ||
103
+ (node.type === 'element' && ((_f = node.content) === null || _f === void 0 ? void 0 : _f.elementType) === 'cms-list-repeater');
104
+ if (isCmsListRepeater && parentDataSource) {
105
+ var content = node.content || node;
106
+ var arrayMapperRenderProp = content.renderPropIdentifier;
107
+ if (arrayMapperRenderProp) {
108
+ // Extract query columns from parent's resource params
109
+ var queryColumns = [];
110
+ if ((_h = (_g = parentDataSource.resourceParams) === null || _g === void 0 ? void 0 : _g.queryColumns) === null || _h === void 0 ? void 0 : _h.content) {
111
+ queryColumns = parentDataSource.resourceParams.queryColumns.content;
112
+ }
113
+ // Extract limit from parent's resource params (for plain array mappers)
114
+ var limit = 0;
115
+ if ((_k = (_j = parentDataSource.resourceParams) === null || _j === void 0 ? void 0 : _j.limit) === null || _k === void 0 ? void 0 : _k.content) {
116
+ limit = parentDataSource.resourceParams.limit.content;
117
+ }
118
+ // For paginated mappers, use perPage from cms-list-repeater
119
+ // For plain mappers, use limit from data-source-list resource params
120
+ var effectivePerPage = content.paginated ? content.perPage : limit || content.perPage;
121
+ var usage = {
122
+ index: index++,
123
+ dataSourceIdentifier: parentDataSource.identifier,
124
+ arrayMapperRenderProp: arrayMapperRenderProp,
125
+ resourceDefinition: {
126
+ dataSourceId: parentDataSource.resourceDef.dataSourceId || '',
127
+ tableName: parentDataSource.resourceDef.tableName || '',
128
+ dataSourceType: parentDataSource.resourceDef.dataSourceType || '',
129
+ },
130
+ paginated: !!content.paginated,
131
+ perPage: effectivePerPage,
132
+ searchEnabled: !!content.searchEnabled,
133
+ searchDebounce: content.searchDebounce || 300,
134
+ queryColumns: queryColumns,
135
+ category: 'plain',
136
+ };
137
+ // Determine category
138
+ if (usage.paginated && usage.searchEnabled) {
139
+ usage.category = 'paginated+search';
140
+ }
141
+ else if (usage.paginated) {
142
+ usage.category = 'paginated-only';
143
+ }
144
+ else if (usage.searchEnabled) {
145
+ usage.category = 'search-only';
146
+ }
147
+ usages.push(usage);
148
+ // Add to maps
149
+ if (!byDataSourceId.has(usage.dataSourceIdentifier)) {
150
+ byDataSourceId.set(usage.dataSourceIdentifier, []);
151
+ }
152
+ byDataSourceId.get(usage.dataSourceIdentifier).push(usage);
153
+ byArrayMapperRenderProp.set(arrayMapperRenderProp, usage);
154
+ }
155
+ // Continue traversing inside the repeater
156
+ if ((_l = content.nodes) === null || _l === void 0 ? void 0 : _l.list) {
157
+ traverse(content.nodes.list, parentDataSource);
158
+ }
159
+ return;
160
+ }
161
+ // Recurse into children
162
+ if (((_m = node.content) === null || _m === void 0 ? void 0 : _m.children) && Array.isArray(node.content.children)) {
163
+ for (var _i = 0, _q = node.content.children; _i < _q.length; _i++) {
164
+ var child = _q[_i];
165
+ traverse(child, parentDataSource);
166
+ }
167
+ }
168
+ if ((_o = node.content) === null || _o === void 0 ? void 0 : _o.node) {
169
+ traverse(node.content.node, parentDataSource);
170
+ }
171
+ if ((_p = node.content) === null || _p === void 0 ? void 0 : _p.nodes) {
172
+ if (node.content.nodes.success) {
173
+ traverse(node.content.nodes.success, parentDataSource);
174
+ }
175
+ if (node.content.nodes.error) {
176
+ traverse(node.content.nodes.error, parentDataSource);
177
+ }
178
+ if (node.content.nodes.loading) {
179
+ traverse(node.content.nodes.loading, parentDataSource);
180
+ }
181
+ if (node.content.nodes.list) {
182
+ traverse(node.content.nodes.list, parentDataSource);
183
+ }
184
+ if (node.content.nodes.empty) {
185
+ traverse(node.content.nodes.empty, parentDataSource);
186
+ }
187
+ }
188
+ if (Array.isArray(node.children)) {
189
+ for (var _r = 0, _s = node.children; _r < _s.length; _r++) {
190
+ var child = _s[_r];
191
+ traverse(child, parentDataSource);
192
+ }
193
+ }
194
+ };
195
+ traverse(uidlNode);
196
+ return { usages: usages, byDataSourceId: byDataSourceId, byArrayMapperRenderProp: byArrayMapperRenderProp };
197
+ }
198
+ // Generate state variable names for a usage
199
+ function getStateVarsForUsage(usage) {
200
+ var idx = usage.index;
201
+ return {
202
+ pageStateVar: "ds_".concat(idx, "_page"),
203
+ setPageStateVar: "setDs_".concat(idx, "_page"),
204
+ maxPagesStateVar: "ds_".concat(idx, "_maxPages"),
205
+ setMaxPagesStateVar: "setDs_".concat(idx, "_maxPages"),
206
+ searchQueryVar: "ds_".concat(idx, "_searchQuery"),
207
+ setSearchQueryVar: "setDs_".concat(idx, "_searchQuery"),
208
+ debouncedSearchQueryVar: "ds_".concat(idx, "_debouncedQuery"),
209
+ setDebouncedSearchQueryVar: "setDs_".concat(idx, "_debouncedQuery"),
210
+ combinedStateVar: "ds_".concat(idx, "_state"),
211
+ setCombinedStateVar: "setDs_".concat(idx, "_state"),
212
+ skipDebounceRefVar: "ds_".concat(idx, "_skipDebounce"),
213
+ skipCountFetchRefVar: "ds_".concat(idx, "_skipCountFetch"),
214
+ propsPrefix: "".concat(usage.dataSourceIdentifier, "_ds_").concat(idx),
215
+ };
216
+ }
217
+ // ==================== MAIN PLUGIN ====================
76
218
  var createNextArrayMapperPaginationPlugin = function () {
77
219
  var paginationPlugin = function (structure) { return __awaiter(void 0, void 0, void 0, function () {
78
- 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;
79
- var _b, _c, _d;
80
- return __generator(this, function (_e) {
220
+ var uidl, chunks, dependencies, options, componentChunk, variableDeclaration, declarator, arrowFunction, blockStatement, registry, getStaticPropsChunk, isPage, stateDeclarations, effectStatements, returnIndex, insertIndex, dataProviders, dataProvidersWithRepeaters, usageIndexByDataSourceId, dataProvidersWithoutRepeaters, searchInputs, searchEnabledUsages, paginationNodes, paginatedUsages;
221
+ return __generator(this, function (_a) {
81
222
  uidl = structure.uidl, chunks = structure.chunks, dependencies = structure.dependencies, options = structure.options;
82
223
  componentChunk = chunks.find(function (chunk) { return chunk.name === 'jsx-component'; });
83
224
  if (!componentChunk || componentChunk.type !== teleport_types_1.ChunkType.AST) {
@@ -99,22 +240,19 @@ var createNextArrayMapperPaginationPlugin = function () {
99
240
  return [2 /*return*/, structure];
100
241
  }
101
242
  blockStatement = arrowFunction.body;
102
- _a = detectPaginationsAndSearchFromJSX(blockStatement, uidl.node), paginatedMappers = _a.paginatedMappers, searchOnlyMappers = _a.searchOnlyMappers, paginationOnlyMappers = _a.paginationOnlyMappers;
103
- if (paginatedMappers.length === 0 &&
104
- searchOnlyMappers.length === 0 &&
105
- paginationOnlyMappers.length === 0) {
243
+ registry = buildStateRegistry(uidl.node);
244
+ if (registry.usages.length === 0) {
106
245
  return [2 /*return*/, structure];
107
246
  }
108
- detectedPaginations = __spreadArray(__spreadArray([], paginatedMappers, true), paginationOnlyMappers, true);
109
- detectedSearchOnly = searchOnlyMappers;
247
+ getStaticPropsChunk = chunks.find(function (chunk) { return chunk.name === 'getStaticProps'; });
248
+ isPage = !!getStaticPropsChunk;
249
+ // Add React dependencies
110
250
  if (!dependencies.useState) {
111
251
  dependencies.useState = {
112
252
  type: 'library',
113
253
  path: 'react',
114
254
  version: '',
115
- meta: {
116
- namedImport: true,
117
- },
255
+ meta: { namedImport: true },
118
256
  };
119
257
  }
120
258
  if (!dependencies.useMemo) {
@@ -122,9 +260,7 @@ var createNextArrayMapperPaginationPlugin = function () {
122
260
  type: 'library',
123
261
  path: 'react',
124
262
  version: '',
125
- meta: {
126
- namedImport: true,
127
- },
263
+ meta: { namedImport: true },
128
264
  };
129
265
  }
130
266
  if (!dependencies.useCallback) {
@@ -132,9 +268,7 @@ var createNextArrayMapperPaginationPlugin = function () {
132
268
  type: 'library',
133
269
  path: 'react',
134
270
  version: '',
135
- meta: {
136
- namedImport: true,
137
- },
271
+ meta: { namedImport: true },
138
272
  };
139
273
  }
140
274
  if (!dependencies.useRef) {
@@ -142,326 +276,306 @@ var createNextArrayMapperPaginationPlugin = function () {
142
276
  type: 'library',
143
277
  path: 'react',
144
278
  version: '',
145
- meta: {
146
- namedImport: true,
147
- },
279
+ meta: { namedImport: true },
280
+ };
281
+ }
282
+ if (!dependencies.useEffect) {
283
+ dependencies.useEffect = {
284
+ type: 'library',
285
+ path: 'react',
286
+ version: '',
287
+ meta: { namedImport: true },
148
288
  };
149
289
  }
150
290
  if (!componentChunk.meta) {
151
291
  componentChunk.meta = {};
152
292
  }
153
293
  componentChunk.meta.isClientComponent = true;
154
- paginationInfos = [];
155
- getStaticPropsChunk = chunks.find(function (chunk) { return chunk.name === 'getStaticProps'; });
156
- isPage = !!getStaticPropsChunk;
157
- isComponent = !isPage;
158
- opts = options;
159
- perPageMap = ((_b = opts.paginationConfig) === null || _b === void 0 ? void 0 : _b.perPageMap) || new Map();
160
- searchConfigMap = ((_c = opts.paginationConfig) === null || _c === void 0 ? void 0 : _c.searchConfigMap) || new Map();
161
- queryColumnsMap = ((_d = opts.paginationConfig) === null || _d === void 0 ? void 0 : _d.queryColumnsMap) || new Map();
162
294
  stateDeclarations = [];
163
- detectedPaginations.forEach(function (detected, index) {
164
- var paginationNodeId = "pg_".concat(index);
165
- // Use arrayMapperRenderProp if available, otherwise fall back to dataSourceIdentifier
166
- var lookupKey = detected.arrayMapperRenderProp || detected.dataSourceIdentifier;
167
- var perPage = perPageMap.get(lookupKey) || 10;
168
- var searchConfig = searchConfigMap.get(lookupKey);
169
- // queryColumns is keyed by dataSourceIdentifier, not array mapper render prop
170
- var queryColumns = queryColumnsMap.get(detected.dataSourceIdentifier);
171
- var info = (0, array_mapper_pagination_1.generatePaginationLogic)(paginationNodeId, detected.dataSourceIdentifier, perPage, searchConfig, queryColumns);
172
- paginationInfos.push(info);
173
- // Add refs to track first render for each useEffect (add first)
174
- if (info.searchEnabled) {
175
- var skipCountFetchOnMountRefVar = "skipCountFetchOnMount_pg_".concat(index);
176
- var skipCountFetchRefAST = types.variableDeclaration('const', [
177
- types.variableDeclarator(types.identifier(skipCountFetchOnMountRefVar), types.callExpression(types.identifier('useRef'), [types.booleanLiteral(true)])),
178
- ]);
179
- stateDeclarations.push(skipCountFetchRefAST);
180
- info.skipCountFetchOnMountRefVar = skipCountFetchOnMountRefVar;
181
- var skipDebounceOnMountRefVar = "skipDebounceOnMount_pg_".concat(index);
182
- var skipDebounceRefAST = types.variableDeclaration('const', [
183
- types.variableDeclarator(types.identifier(skipDebounceOnMountRefVar), types.callExpression(types.identifier('useRef'), [types.booleanLiteral(true)])),
184
- ]);
185
- stateDeclarations.push(skipDebounceRefAST);
186
- info.skipDebounceOnMountRefVar = skipDebounceOnMountRefVar;
295
+ effectStatements = [];
296
+ registry.usages.forEach(function (usage) {
297
+ if (usage.category === 'plain') {
298
+ return; // Plain mappers don't need state
187
299
  }
188
- // Add maxPages state
189
- var maxPagesStateVar = "".concat(info.pageStateVar.replace('_page', ''), "_maxPages");
190
- var setMaxPagesStateVar = "set".concat(maxPagesStateVar.charAt(0).toUpperCase() + maxPagesStateVar.slice(1));
191
- // For pages: initialize from props (with pagination-specific prop name), for components: initialize to 0
192
- var maxPagesInitValue = isPage
193
- ? types.logicalExpression('||', types.optionalMemberExpression(types.identifier('props'), types.identifier("".concat(info.dataSourceIdentifier, "_pg_").concat(index, "_maxPages")), false, true), types.numericLiteral(0))
194
- : types.numericLiteral(0);
195
- var maxPagesStateAST = types.variableDeclaration('const', [
196
- types.variableDeclarator(types.arrayPattern([
197
- types.identifier(maxPagesStateVar),
198
- types.identifier(setMaxPagesStateVar),
199
- ]), types.callExpression(types.identifier('useState'), [maxPagesInitValue])),
200
- ]);
201
- stateDeclarations.push(maxPagesStateAST);
202
- info.maxPagesStateVar = maxPagesStateVar;
203
- info.setMaxPagesStateVar = setMaxPagesStateVar;
204
- // If both pagination and search are enabled, combine them into a single state object
205
- if (info.searchEnabled && info.searchQueryVar && info.setSearchQueryVar) {
206
- // Combined state: { page: 1, debouncedQuery: '' }
207
- var combinedStateVar = "paginationState_pg_".concat(index);
208
- var setCombinedStateVar = "setPaginationState_pg_".concat(index);
209
- var combinedStateAST = types.variableDeclaration('const', [
300
+ var vars = getStateVarsForUsage(usage);
301
+ if (usage.category === 'paginated+search') {
302
+ // Combined state object for pagination + search
303
+ stateDeclarations.push(types.variableDeclaration('const', [
304
+ types.variableDeclarator(types.identifier(vars.skipDebounceRefVar), types.callExpression(types.identifier('useRef'), [types.booleanLiteral(true)])),
305
+ ]));
306
+ // Only add skipCountFetchRef for pages (where we have server-side count)
307
+ // For components, we need to fetch count on mount
308
+ if (isPage) {
309
+ stateDeclarations.push(types.variableDeclaration('const', [
310
+ types.variableDeclarator(types.identifier(vars.skipCountFetchRefVar), types.callExpression(types.identifier('useRef'), [types.booleanLiteral(true)])),
311
+ ]));
312
+ }
313
+ // maxPages state
314
+ var maxPagesInit = isPage
315
+ ? types.logicalExpression('||', types.optionalMemberExpression(types.identifier('props'), types.identifier("".concat(vars.propsPrefix, "_maxPages")), false, true), types.numericLiteral(0))
316
+ : types.numericLiteral(0);
317
+ stateDeclarations.push(types.variableDeclaration('const', [
210
318
  types.variableDeclarator(types.arrayPattern([
211
- types.identifier(combinedStateVar),
212
- types.identifier(setCombinedStateVar),
319
+ types.identifier(vars.maxPagesStateVar),
320
+ types.identifier(vars.setMaxPagesStateVar),
321
+ ]), types.callExpression(types.identifier('useState'), [maxPagesInit])),
322
+ ]));
323
+ // Combined state { page, debouncedQuery }
324
+ stateDeclarations.push(types.variableDeclaration('const', [
325
+ types.variableDeclarator(types.arrayPattern([
326
+ types.identifier(vars.combinedStateVar),
327
+ types.identifier(vars.setCombinedStateVar),
213
328
  ]), types.callExpression(types.identifier('useState'), [
214
329
  types.objectExpression([
215
330
  types.objectProperty(types.identifier('page'), types.numericLiteral(1)),
216
331
  types.objectProperty(types.identifier('debouncedQuery'), types.stringLiteral('')),
217
332
  ]),
218
333
  ])),
219
- ]);
220
- stateDeclarations.push(combinedStateAST);
221
- // Still need the immediate search query state for the input
222
- var searchStateAST = types.variableDeclaration('const', [
334
+ ]));
335
+ // Immediate search query state
336
+ stateDeclarations.push(types.variableDeclaration('const', [
223
337
  types.variableDeclarator(types.arrayPattern([
224
- types.identifier(info.searchQueryVar),
225
- types.identifier(info.setSearchQueryVar),
338
+ types.identifier(vars.searchQueryVar),
339
+ types.identifier(vars.setSearchQueryVar),
226
340
  ]), types.callExpression(types.identifier('useState'), [types.stringLiteral('')])),
227
- ]);
228
- stateDeclarations.push(searchStateAST);
229
- info.combinedStateVar = combinedStateVar;
230
- info.setCombinedStateVar = setCombinedStateVar;
231
- }
232
- else {
233
- // If search is not enabled, just add regular page state
234
- var pageStateAST = types.variableDeclaration('const', [
235
- types.variableDeclarator(types.arrayPattern([
236
- types.identifier(info.pageStateVar),
237
- types.identifier(info.setPageStateVar),
238
- ]), types.callExpression(types.identifier('useState'), [types.numericLiteral(1)])),
239
- ]);
240
- stateDeclarations.push(pageStateAST);
241
- }
242
- });
243
- // Add all state declarations at once to the beginning in correct order
244
- stateDeclarations.reverse().forEach(function (stateDecl) {
245
- blockStatement.body.unshift(stateDecl);
246
- });
247
- hasSearchEnabled = paginationInfos.some(function (info) { return info.searchEnabled; });
248
- if (hasSearchEnabled && !dependencies.useEffect) {
249
- dependencies.useEffect = {
250
- type: 'library',
251
- path: 'react',
252
- version: '',
253
- meta: {
254
- namedImport: true,
255
- },
256
- };
257
- }
258
- firstReturnIndex = blockStatement.body.findIndex(function (stmt) { return stmt.type === 'ReturnStatement'; });
259
- insertIndex = firstReturnIndex !== -1 ? firstReturnIndex : blockStatement.body.length;
260
- // Add effects in reverse order so they appear in correct order
261
- paginationInfos.forEach(function (info) {
262
- if (info.searchEnabled &&
263
- info.searchQueryVar &&
264
- info.debouncedSearchQueryVar &&
265
- info.setDebouncedSearchQueryVar) {
266
- // Add effect that updates debounced search after delay
267
- var skipDebounceOnMountRefVar = info.skipDebounceOnMountRefVar;
268
- var setCombinedStateVar = info.setCombinedStateVar;
269
- var debounceEffect = types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
341
+ ]));
342
+ // Debounce effect
343
+ effectStatements.push(types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
270
344
  types.arrowFunctionExpression([], types.blockStatement([
271
- types.ifStatement(types.memberExpression(types.identifier(skipDebounceOnMountRefVar), types.identifier('current')), types.blockStatement([
272
- types.expressionStatement(types.assignmentExpression('=', types.memberExpression(types.identifier(skipDebounceOnMountRefVar), types.identifier('current')), types.booleanLiteral(false))),
345
+ types.ifStatement(types.memberExpression(types.identifier(vars.skipDebounceRefVar), types.identifier('current')), types.blockStatement([
346
+ types.expressionStatement(types.assignmentExpression('=', types.memberExpression(types.identifier(vars.skipDebounceRefVar), types.identifier('current')), types.booleanLiteral(false))),
273
347
  types.returnStatement(),
274
348
  ])),
275
349
  types.variableDeclaration('const', [
276
350
  types.variableDeclarator(types.identifier('timer'), types.callExpression(types.identifier('setTimeout'), [
277
351
  types.arrowFunctionExpression([], types.blockStatement([
278
- types.expressionStatement(types.callExpression(types.identifier(setCombinedStateVar), [
352
+ types.expressionStatement(types.callExpression(types.identifier(vars.setCombinedStateVar), [
279
353
  types.objectExpression([
280
354
  types.objectProperty(types.identifier('page'), types.numericLiteral(1)),
281
- types.objectProperty(types.identifier('debouncedQuery'), types.identifier(info.searchQueryVar)),
355
+ types.objectProperty(types.identifier('debouncedQuery'), types.identifier(vars.searchQueryVar)),
282
356
  ]),
283
357
  ])),
284
358
  ])),
285
- types.numericLiteral(info.searchDebounce || 300),
359
+ types.numericLiteral(usage.searchDebounce),
286
360
  ])),
287
361
  ]),
288
362
  types.returnStatement(types.arrowFunctionExpression([], types.callExpression(types.identifier('clearTimeout'), [
289
363
  types.identifier('timer'),
290
364
  ]))),
291
365
  ])),
292
- types.arrayExpression([types.identifier(info.searchQueryVar)]),
293
- ]));
294
- blockStatement.body.splice(insertIndex, 0, debounceEffect);
295
- // Add useEffect to refetch count when search changes (for both pages and components)
296
- var detected = detectedPaginations.find(function (d) { return d.dataSourceIdentifier === info.dataSourceIdentifier; });
297
- if (!detected) {
298
- return;
366
+ types.arrayExpression([types.identifier(vars.searchQueryVar)]),
367
+ ])));
368
+ // Count refetch effect
369
+ var fileName = (0, utils_1.generateSafeFileName)(usage.resourceDefinition.dataSourceType, usage.resourceDefinition.tableName, usage.resourceDefinition.dataSourceId);
370
+ var urlParams = [
371
+ types.objectProperty(types.identifier('query'), types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('debouncedQuery'))),
372
+ ];
373
+ if (usage.queryColumns.length > 0) {
374
+ urlParams.push(types.objectProperty(types.identifier('queryColumns'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [types.arrayExpression(usage.queryColumns.map(function (c) { return types.stringLiteral(c); }))])));
299
375
  }
300
- var resourceDefAttr = detected.dataProviderJSX.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'resourceDefinition'; });
301
- if (resourceDefAttr &&
302
- resourceDefAttr.value &&
303
- resourceDefAttr.value.type === 'JSXExpressionContainer') {
304
- var resourceDef = resourceDefAttr.value.expression;
305
- if (resourceDef.type === 'ObjectExpression') {
306
- var dataSourceIdProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'dataSourceId'; });
307
- var tableNameProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'tableName'; });
308
- var dataSourceTypeProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'dataSourceType'; });
309
- if (dataSourceIdProp && tableNameProp && dataSourceTypeProp) {
310
- var dataSourceId = dataSourceIdProp.value.value;
311
- var tableName = tableNameProp.value.value;
312
- var dataSourceType = dataSourceTypeProp.value.value;
313
- var fileName = "".concat(dataSourceType, "-").concat(tableName, "-").concat(dataSourceId.substring(0, 8));
314
- var setMaxPagesStateVar = info.setMaxPagesStateVar;
315
- // Create useEffect to refetch count when debounced search changes
316
- var skipCountFetchOnMountRefVar = info.skipCountFetchOnMountRefVar;
317
- var combinedStateVar = info.combinedStateVar;
318
- // Build URLSearchParams properties - query is always included, queryColumns is optional
319
- var urlSearchParamsProperties = [
320
- types.objectProperty(types.identifier('query'), types.memberExpression(types.identifier(combinedStateVar), types.identifier('debouncedQuery'))),
321
- ];
322
- // Add queryColumns only if they exist
323
- if (info.queryColumns && info.queryColumns.length > 0) {
324
- urlSearchParamsProperties.push(types.objectProperty(types.identifier('queryColumns'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [
325
- types.arrayExpression(info.queryColumns.map(function (col) { return types.stringLiteral(col); })),
326
- ])));
327
- }
328
- var refetchCountEffect = types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
329
- types.arrowFunctionExpression([], types.blockStatement([
330
- types.ifStatement(types.memberExpression(types.identifier(skipCountFetchOnMountRefVar), types.identifier('current')), types.blockStatement([
331
- types.expressionStatement(types.assignmentExpression('=', types.memberExpression(types.identifier(skipCountFetchOnMountRefVar), types.identifier('current')), types.booleanLiteral(false))),
332
- types.returnStatement(),
333
- ])),
334
- types.expressionStatement(types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.callExpression(types.identifier('fetch'), [
335
- types.templateLiteral([
336
- types.templateElement({
337
- raw: "/api/".concat(fileName, "-count?"),
338
- cooked: "/api/".concat(fileName, "-count?"),
339
- }),
340
- types.templateElement({ raw: '', cooked: '' }),
341
- ], [
342
- types.newExpression(types.identifier('URLSearchParams'), [
343
- types.objectExpression(urlSearchParamsProperties),
344
- ]),
345
- ]),
346
- ]), types.identifier('then')), [
347
- types.arrowFunctionExpression([types.identifier('res')], types.callExpression(types.memberExpression(types.identifier('res'), types.identifier('json')), [])),
348
- ]), types.identifier('then')), [
349
- types.arrowFunctionExpression([types.identifier('data')], types.blockStatement([
350
- types.ifStatement(types.logicalExpression('&&', types.identifier('data'), types.binaryExpression('in', types.stringLiteral('count'), types.identifier('data'))), types.blockStatement([
351
- types.expressionStatement(types.callExpression(types.identifier(setMaxPagesStateVar), [
352
- 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')), [
353
- types.binaryExpression('/', types.memberExpression(types.identifier('data'), types.identifier('count')), types.numericLiteral(info.perPage)),
354
- ])),
355
- ])),
376
+ // Build the count fetch effect body
377
+ var countFetchEffectBody = [];
378
+ // Only add skip-on-mount check for pages (where we have server-side count)
379
+ if (isPage) {
380
+ countFetchEffectBody.push(types.ifStatement(types.memberExpression(types.identifier(vars.skipCountFetchRefVar), types.identifier('current')), types.blockStatement([
381
+ types.expressionStatement(types.assignmentExpression('=', types.memberExpression(types.identifier(vars.skipCountFetchRefVar), types.identifier('current')), types.booleanLiteral(false))),
382
+ types.returnStatement(),
383
+ ])));
384
+ }
385
+ // Add the fetch call
386
+ countFetchEffectBody.push(types.expressionStatement(types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.callExpression(types.identifier('fetch'), [
387
+ types.templateLiteral([
388
+ types.templateElement({
389
+ raw: "/api/".concat(fileName, "-count?"),
390
+ cooked: "/api/".concat(fileName, "-count?"),
391
+ }),
392
+ types.templateElement({ raw: '', cooked: '' }),
393
+ ], [
394
+ types.newExpression(types.identifier('URLSearchParams'), [
395
+ types.objectExpression(urlParams),
396
+ ]),
397
+ ]),
398
+ ]), types.identifier('then')), [
399
+ types.arrowFunctionExpression([types.identifier('res')], types.callExpression(types.memberExpression(types.identifier('res'), types.identifier('json')), [])),
400
+ ]), types.identifier('then')), [
401
+ types.arrowFunctionExpression([types.identifier('data')], types.blockStatement([
402
+ types.ifStatement(types.logicalExpression('&&', types.identifier('data'), types.binaryExpression('in', types.stringLiteral('count'), types.identifier('data'))), types.blockStatement([
403
+ types.expressionStatement(types.callExpression(types.identifier(vars.setMaxPagesStateVar), [
404
+ 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')), [
405
+ types.binaryExpression('/', types.memberExpression(types.identifier('data'), types.identifier('count')), types.numericLiteral(usage.perPage)),
406
+ ])),
407
+ ])),
408
+ ])),
409
+ ])),
410
+ ])));
411
+ effectStatements.push(types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
412
+ types.arrowFunctionExpression([], types.blockStatement(countFetchEffectBody)),
413
+ types.arrayExpression([
414
+ types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('debouncedQuery')),
415
+ ]),
416
+ ])));
417
+ }
418
+ else if (usage.category === 'paginated-only') {
419
+ // Simple page state
420
+ var maxPagesInit = isPage
421
+ ? types.logicalExpression('||', types.optionalMemberExpression(types.identifier('props'), types.identifier("".concat(vars.propsPrefix, "_maxPages")), false, true), types.numericLiteral(0))
422
+ : types.numericLiteral(0);
423
+ stateDeclarations.push(types.variableDeclaration('const', [
424
+ types.variableDeclarator(types.arrayPattern([
425
+ types.identifier(vars.maxPagesStateVar),
426
+ types.identifier(vars.setMaxPagesStateVar),
427
+ ]), types.callExpression(types.identifier('useState'), [maxPagesInit])),
428
+ ]));
429
+ stateDeclarations.push(types.variableDeclaration('const', [
430
+ types.variableDeclarator(types.arrayPattern([
431
+ types.identifier(vars.pageStateVar),
432
+ types.identifier(vars.setPageStateVar),
433
+ ]), types.callExpression(types.identifier('useState'), [types.numericLiteral(1)])),
434
+ ]));
435
+ // For components (not pages), add a useEffect to fetch count on mount
436
+ // Pages get count from getStaticProps, but components need to fetch it client-side
437
+ if (!isPage) {
438
+ var fileName = (0, utils_1.generateSafeFileName)(usage.resourceDefinition.dataSourceType, usage.resourceDefinition.tableName, usage.resourceDefinition.dataSourceId);
439
+ effectStatements.push(types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
440
+ types.arrowFunctionExpression([], types.blockStatement([
441
+ types.expressionStatement(types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.callExpression(types.identifier('fetch'), [
442
+ types.stringLiteral("/api/".concat(fileName, "-count")),
443
+ ]), types.identifier('then')), [
444
+ types.arrowFunctionExpression([types.identifier('res')], types.callExpression(types.memberExpression(types.identifier('res'), types.identifier('json')), [])),
445
+ ]), types.identifier('then')), [
446
+ types.arrowFunctionExpression([types.identifier('data')], types.blockStatement([
447
+ types.ifStatement(types.logicalExpression('&&', types.identifier('data'), types.binaryExpression('in', types.stringLiteral('count'), types.identifier('data'))), types.blockStatement([
448
+ types.expressionStatement(types.callExpression(types.identifier(vars.setMaxPagesStateVar), [
449
+ 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')), [
450
+ types.binaryExpression('/', types.memberExpression(types.identifier('data'), types.identifier('count')), types.numericLiteral(usage.perPage)),
356
451
  ])),
357
452
  ])),
358
453
  ])),
359
454
  ])),
360
- types.arrayExpression([
361
- types.memberExpression(types.identifier(combinedStateVar), types.identifier('debouncedQuery')),
362
- ]),
363
- ]));
364
- blockStatement.body.splice(insertIndex, 0, refetchCountEffect);
365
- }
366
- }
455
+ ])),
456
+ ])),
457
+ types.arrayExpression([]), // Empty dependency array - fetch on mount only
458
+ ])));
367
459
  }
368
460
  }
369
- });
370
- // For components, add useEffect to fetch count on mount
371
- if (isComponent) {
372
- if (!dependencies.useEffect) {
373
- dependencies.useEffect = {
374
- type: 'library',
375
- path: 'react',
376
- version: '',
377
- meta: {
378
- namedImport: true,
379
- },
380
- };
381
- }
382
- dataSourceToInfos_1 = new Map();
383
- paginationInfos.forEach(function (info) {
384
- var detected = detectedPaginations.find(function (d) { return d.dataSourceIdentifier === info.dataSourceIdentifier; });
385
- if (!detected) {
386
- return;
387
- }
388
- var resourceDefAttr = detected.dataProviderJSX.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'resourceDefinition'; });
389
- if (!resourceDefAttr ||
390
- !resourceDefAttr.value ||
391
- resourceDefAttr.value.type !== 'JSXExpressionContainer') {
392
- return;
393
- }
394
- var resourceDef = resourceDefAttr.value.expression;
395
- if (resourceDef.type !== 'ObjectExpression') {
396
- return;
397
- }
398
- var dataSourceIdProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'dataSourceId'; });
399
- var tableNameProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'tableName'; });
400
- var dataSourceTypeProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'dataSourceType'; });
401
- if (!dataSourceIdProp || !tableNameProp || !dataSourceTypeProp) {
402
- return;
403
- }
404
- var dataSourceId = dataSourceIdProp.value.value;
405
- var tableName = tableNameProp.value.value;
406
- var dataSourceType = dataSourceTypeProp.value.value;
407
- var fileName = "".concat(dataSourceType, "-").concat(tableName, "-").concat(dataSourceId.substring(0, 8));
408
- // Group by data source identifier
409
- if (!dataSourceToInfos_1.has(info.dataSourceIdentifier)) {
410
- dataSourceToInfos_1.set(info.dataSourceIdentifier, []);
411
- }
412
- dataSourceToInfos_1.get(info.dataSourceIdentifier).push({ info: info, detected: detected, fileName: fileName });
413
- });
414
- componentUseEffects_1 = [];
415
- dataSourceToInfos_1.forEach(function (infos) {
416
- var fileName = infos[0].fileName;
417
- // Create array of setState calls - one for each pagination using this data source
418
- var setStateStatements = infos.map(function (_a) {
419
- var info = _a.info;
420
- var setMaxPagesStateVar = info.setMaxPagesStateVar;
421
- return types.expressionStatement(types.callExpression(types.identifier(setMaxPagesStateVar), [
422
- types.callExpression(types.memberExpression(types.identifier('Math'), types.identifier('ceil')), [
423
- types.binaryExpression('/', types.memberExpression(types.identifier('data'), types.identifier('count')), types.numericLiteral(info.perPage)),
424
- ]),
425
- ]));
426
- });
427
- // Create useEffect to fetch count on mount - sets ALL maxPages for this data source
428
- var useEffectAST = types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
461
+ else if (usage.category === 'search-only') {
462
+ // Search-only state
463
+ stateDeclarations.push(types.variableDeclaration('const', [
464
+ types.variableDeclarator(types.identifier(vars.skipDebounceRefVar), types.callExpression(types.identifier('useRef'), [types.booleanLiteral(true)])),
465
+ ]));
466
+ stateDeclarations.push(types.variableDeclaration('const', [
467
+ types.variableDeclarator(types.arrayPattern([
468
+ types.identifier(vars.debouncedSearchQueryVar),
469
+ types.identifier(vars.setDebouncedSearchQueryVar),
470
+ ]), types.callExpression(types.identifier('useState'), [types.stringLiteral('')])),
471
+ ]));
472
+ stateDeclarations.push(types.variableDeclaration('const', [
473
+ types.variableDeclarator(types.arrayPattern([
474
+ types.identifier(vars.searchQueryVar),
475
+ types.identifier(vars.setSearchQueryVar),
476
+ ]), types.callExpression(types.identifier('useState'), [types.stringLiteral('')])),
477
+ ]));
478
+ // Debounce effect
479
+ effectStatements.push(types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
429
480
  types.arrowFunctionExpression([], types.blockStatement([
430
- types.expressionStatement(types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.callExpression(types.identifier('fetch'), [
431
- types.stringLiteral("/api/".concat(fileName, "-count")),
432
- ]), types.identifier('then')), [
433
- types.arrowFunctionExpression([types.identifier('res')], types.callExpression(types.memberExpression(types.identifier('res'), types.identifier('json')), [])),
434
- ]), types.identifier('then')), [
435
- types.arrowFunctionExpression([types.identifier('data')], types.blockStatement([
436
- types.ifStatement(types.logicalExpression('&&', types.identifier('data'), types.memberExpression(types.identifier('data'), types.identifier('count'))), types.blockStatement(setStateStatements)),
437
- ])),
481
+ types.ifStatement(types.memberExpression(types.identifier(vars.skipDebounceRefVar), types.identifier('current')), types.blockStatement([
482
+ types.expressionStatement(types.assignmentExpression('=', types.memberExpression(types.identifier(vars.skipDebounceRefVar), types.identifier('current')), types.booleanLiteral(false))),
483
+ types.returnStatement(),
438
484
  ])),
485
+ types.variableDeclaration('const', [
486
+ types.variableDeclarator(types.identifier('timer'), types.callExpression(types.identifier('setTimeout'), [
487
+ types.arrowFunctionExpression([], types.blockStatement([
488
+ types.expressionStatement(types.callExpression(types.identifier(vars.setDebouncedSearchQueryVar), [types.identifier(vars.searchQueryVar)])),
489
+ ])),
490
+ types.numericLiteral(usage.searchDebounce),
491
+ ])),
492
+ ]),
493
+ types.returnStatement(types.arrowFunctionExpression([], types.callExpression(types.identifier('clearTimeout'), [
494
+ types.identifier('timer'),
495
+ ]))),
439
496
  ])),
440
- types.arrayExpression([]),
441
- ]));
442
- componentUseEffects_1.push(useEffectAST);
443
- });
444
- componentReturnIndex = blockStatement.body.findIndex(function (stmt) { return stmt.type === 'ReturnStatement'; });
445
- componentEffectsInsertIndex_1 = componentReturnIndex !== -1 ? componentReturnIndex : blockStatement.body.length;
446
- // Insert in reverse order to maintain correct order
447
- componentUseEffects_1.reverse().forEach(function (effect) {
448
- blockStatement.body.splice(componentEffectsInsertIndex_1, 0, effect);
449
- });
450
- }
451
- createAPIRoutesForPaginatedDataSources(uidl.node, options.dataSources, componentChunk, options.extractedResources, paginationInfos, isComponent);
452
- detectedPaginations.forEach(function (detected, index) {
453
- addPaginationParamsToDataProvider(detected.dataProviderJSX, paginationInfos[index], index);
497
+ types.arrayExpression([types.identifier(vars.searchQueryVar)]),
498
+ ])));
499
+ }
500
+ });
501
+ // Insert state declarations at the beginning
502
+ stateDeclarations.reverse().forEach(function (s) { return blockStatement.body.unshift(s); });
503
+ returnIndex = blockStatement.body.findIndex(function (s) { return s.type === 'ReturnStatement'; });
504
+ insertIndex = returnIndex !== -1 ? returnIndex : blockStatement.body.length;
505
+ effectStatements.reverse().forEach(function (e) { return blockStatement.body.splice(insertIndex, 0, e); });
506
+ dataProviders = findAllDataProvidersInJSX(blockStatement);
507
+ dataProvidersWithRepeaters = dataProviders.filter(function (dp) {
508
+ var hasRepeater = findArrayMapperRenderPropInDataProvider(dp) !== undefined;
509
+ return hasRepeater;
510
+ });
511
+ usageIndexByDataSourceId = new Map();
512
+ dataProvidersWithRepeaters.forEach(function (dp) {
513
+ var _a, _b;
514
+ var nameAttr = dp.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'name'; });
515
+ if (!((_b = (_a = nameAttr === null || nameAttr === void 0 ? void 0 : nameAttr.value) === null || _a === void 0 ? void 0 : _a.expression) === null || _b === void 0 ? void 0 : _b.value)) {
516
+ return;
517
+ }
518
+ var dataSourceIdentifier = nameAttr.value.expression.value;
519
+ // Use pure order-based matching within each dataSourceIdentifier
520
+ var usages = registry.byDataSourceId.get(dataSourceIdentifier) || [];
521
+ var currentIndex = usageIndexByDataSourceId.get(dataSourceIdentifier) || 0;
522
+ if (currentIndex >= usages.length) {
523
+ return;
524
+ }
525
+ var usage = usages[currentIndex];
526
+ usageIndexByDataSourceId.set(dataSourceIdentifier, currentIndex + 1);
527
+ var vars = getStateVarsForUsage(usage);
528
+ var fileName = (0, utils_1.generateSafeFileName)(usage.resourceDefinition.dataSourceType, usage.resourceDefinition.tableName, usage.resourceDefinition.dataSourceId);
529
+ // Update DataProvider based on category
530
+ if (usage.category === 'paginated+search') {
531
+ updateDataProviderForPaginatedSearch(dp, usage, vars, fileName);
532
+ }
533
+ else if (usage.category === 'paginated-only') {
534
+ updateDataProviderForPaginationOnly(dp, usage, vars, fileName);
535
+ }
536
+ else if (usage.category === 'search-only') {
537
+ updateDataProviderForSearchOnly(dp, usage, vars, fileName);
538
+ }
539
+ else {
540
+ updateDataProviderForPlain(dp, vars);
541
+ }
542
+ // Create API route if needed
543
+ if (usage.category !== 'plain') {
544
+ ensureAPIRouteExists(options.extractedResources, usage);
545
+ }
454
546
  });
455
- modifyPaginationButtons(blockStatement, detectedPaginations, paginationInfos);
456
- modifySearchInputs(blockStatement, detectedPaginations, paginationInfos);
547
+ dataProvidersWithoutRepeaters = dataProviders.filter(function (dp) {
548
+ var hasRepeater = findArrayMapperRenderPropInDataProvider(dp) !== undefined;
549
+ return !hasRepeater;
550
+ });
551
+ dataProvidersWithoutRepeaters.forEach(function (dp) {
552
+ stabilizeDataProviderWithoutRepeater(dp);
553
+ });
554
+ searchInputs = findAllSearchInputsInJSX(blockStatement);
555
+ searchEnabledUsages = registry.usages.filter(function (u) { return u.searchEnabled; });
556
+ // Match by order - search input 0 -> searchEnabledUsages[0], etc.
557
+ searchInputs.forEach(function (input, idx) {
558
+ if (idx >= searchEnabledUsages.length) {
559
+ return;
560
+ }
561
+ var usage = searchEnabledUsages[idx];
562
+ var vars = getStateVarsForUsage(usage);
563
+ wireSearchInput(input.node, vars);
564
+ });
565
+ paginationNodes = findAllPaginationNodesInJSX(blockStatement);
566
+ paginatedUsages = registry.usages.filter(function (u) { return u.paginated; });
567
+ // Match by order - pagination node 0 -> paginatedUsages[0], etc.
568
+ paginationNodes.forEach(function (paginationNode, idx) {
569
+ if (idx >= paginatedUsages.length) {
570
+ return;
571
+ }
572
+ var usage = paginatedUsages[idx];
573
+ var vars = getStateVarsForUsage(usage);
574
+ wirePaginationButtons(paginationNode.node, usage, vars);
575
+ });
576
+ // STEP 6: Update getStaticProps if this is a page
457
577
  if (isPage) {
458
- modifyGetStaticPropsForPagination(chunks, paginationInfos);
459
- }
460
- searchOnlyDataSources = detectedSearchOnly;
461
- if (searchOnlyDataSources.length > 0) {
462
- handleSearchOnlyArrayMappers(blockStatement, searchOnlyDataSources, searchConfigMap, queryColumnsMap, dependencies);
463
- // Create API routes for search-only data sources
464
- createAPIRoutesForSearchOnlyDataSources(uidl.node, options.dataSources, componentChunk, options.extractedResources, searchOnlyDataSources);
578
+ updateGetStaticProps(chunks, registry);
465
579
  }
466
580
  return [2 /*return*/, structure];
467
581
  });
@@ -469,1148 +583,591 @@ var createNextArrayMapperPaginationPlugin = function () {
469
583
  return paginationPlugin;
470
584
  };
471
585
  exports.createNextArrayMapperPaginationPlugin = createNextArrayMapperPaginationPlugin;
472
- function findParentNode(root, target, currentParent) {
473
- if (currentParent === void 0) { currentParent = null; }
474
- if (!root || !target) {
475
- return null;
476
- }
477
- if (root === target) {
478
- return currentParent;
479
- }
480
- if (root.type === 'JSXElement' || root.type === 'JSXFragment') {
481
- if (root.children && Array.isArray(root.children)) {
482
- for (var _i = 0, _a = root.children; _i < _a.length; _i++) {
483
- var child = _a[_i];
484
- var found = findParentNode(child, target, root);
485
- if (found !== null) {
486
- return found;
487
- }
488
- }
586
+ // ==================== HELPER FUNCTIONS ====================
587
+ function findAllDataProvidersInJSX(blockStatement) {
588
+ var results = [];
589
+ var traverse = function (node) {
590
+ var _a, _b;
591
+ if (!node) {
592
+ return;
489
593
  }
490
- }
491
- else if (root.type === 'JSXExpressionContainer') {
492
- if (root.expression) {
493
- var found = findParentNode(root.expression, target, root);
494
- if (found !== null) {
495
- return found;
496
- }
594
+ if (node.type === 'JSXElement' && ((_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.name) === 'DataProvider') {
595
+ results.push(node);
497
596
  }
498
- }
499
- else if (root.type === 'BlockStatement') {
500
- if (root.body && Array.isArray(root.body)) {
501
- for (var _b = 0, _c = root.body; _b < _c.length; _b++) {
502
- var stmt = _c[_b];
503
- var found = findParentNode(stmt, target, root);
504
- if (found !== null) {
505
- return found;
506
- }
507
- }
597
+ if (node.children && Array.isArray(node.children)) {
598
+ node.children.forEach(function (c) { return traverse(c); });
508
599
  }
509
- }
510
- else if (root.type === 'ReturnStatement') {
511
- if (root.argument) {
512
- var found = findParentNode(root.argument, target, root);
513
- if (found !== null) {
514
- return found;
600
+ if (node.body) {
601
+ if (Array.isArray(node.body)) {
602
+ node.body.forEach(function (s) { return traverse(s); });
603
+ }
604
+ else {
605
+ traverse(node.body);
515
606
  }
516
607
  }
517
- }
518
- else if (root.type === 'ConditionalExpression') {
519
- var foundConsequent = findParentNode(root.consequent, target, root);
520
- if (foundConsequent !== null) {
521
- return foundConsequent;
608
+ if (node.consequent) {
609
+ traverse(node.consequent);
522
610
  }
523
- var foundAlternate = findParentNode(root.alternate, target, root);
524
- if (foundAlternate !== null) {
525
- return foundAlternate;
611
+ if (node.alternate) {
612
+ traverse(node.alternate);
526
613
  }
527
- }
528
- return null;
614
+ if (node.expression) {
615
+ traverse(node.expression);
616
+ }
617
+ if (node.argument) {
618
+ traverse(node.argument);
619
+ }
620
+ if (node.arguments) {
621
+ node.arguments.forEach(function (a) { return traverse(a); });
622
+ }
623
+ };
624
+ traverse(blockStatement);
625
+ return results;
529
626
  }
530
- function detectPaginationsAndSearchFromJSX(blockStatement, uidlNode) {
531
- var dataProviderList = [];
532
- var arrayMapperInfoMap = new Map();
533
- if (uidlNode) {
534
- var collectArrayMapperInfo_1 = function (node) {
535
- var _a, _b, _c, _d, _e;
536
- if (!node) {
537
- return;
538
- }
539
- if (node.type === 'data-source-list' && ((_a = node.content) === null || _a === void 0 ? void 0 : _a.renderPropIdentifier)) {
540
- var dataSourceIdentifier_1 = node.content.renderPropIdentifier;
541
- if ((_d = (_c = (_b = node.content.nodes) === null || _b === void 0 ? void 0 : _b.success) === null || _c === void 0 ? void 0 : _c.content) === null || _d === void 0 ? void 0 : _d.children) {
542
- node.content.nodes.success.content.children.forEach(function (child) {
543
- var _a;
544
- if (child.type === 'cms-list-repeater' && ((_a = child.content) === null || _a === void 0 ? void 0 : _a.renderPropIdentifier)) {
545
- var arrayMapperRenderProp = child.content.renderPropIdentifier;
546
- // Key by array mapper render prop (unique), not data source identifier
547
- arrayMapperInfoMap.set(arrayMapperRenderProp, {
548
- dataSourceIdentifier: dataSourceIdentifier_1,
549
- renderProp: arrayMapperRenderProp,
550
- paginated: child.content.paginated || false,
551
- searchEnabled: child.content.searchEnabled || false,
552
- });
553
- }
554
- });
555
- }
556
- }
557
- if ((_e = node.content) === null || _e === void 0 ? void 0 : _e.children) {
558
- node.content.children.forEach(function (child) { return collectArrayMapperInfo_1(child); });
559
- }
560
- if (node.children && Array.isArray(node.children)) {
561
- node.children.forEach(function (child) { return collectArrayMapperInfo_1(child); });
562
- }
563
- };
564
- collectArrayMapperInfo_1(uidlNode);
627
+ function findArrayMapperRenderPropInDataProvider(dataProvider) {
628
+ var _a, _b, _c, _d, _e;
629
+ var renderSuccessAttr = dataProvider.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'renderSuccess'; });
630
+ if (!((_a = renderSuccessAttr === null || renderSuccessAttr === void 0 ? void 0 : renderSuccessAttr.value) === null || _a === void 0 ? void 0 : _a.expression)) {
631
+ return undefined;
565
632
  }
566
- var dataProvidersWithParents = [];
567
- var findDataProvidersAndParents = function (node, parent) {
633
+ var findRepeater = function (node) {
568
634
  var _a, _b;
569
- if (parent === void 0) { parent = null; }
570
635
  if (!node) {
571
- return;
636
+ return null;
572
637
  }
573
- // Check if this is a DataProvider
574
- if (node.type === 'JSXElement' && ((_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.name) === 'DataProvider') {
575
- dataProvidersWithParents.push({
576
- dataProvider: node,
577
- parent: parent,
578
- });
638
+ if (node.type === 'JSXElement' && ((_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.name) === 'Repeater') {
639
+ return node;
579
640
  }
580
- // Only recurse through JSX structure, not into embedded expressions or code
581
- if (node.type === 'ReturnStatement' && node.argument) {
582
- findDataProvidersAndParents(node.argument, parent);
641
+ if (node.body) {
642
+ return findRepeater(node.body);
583
643
  }
584
- else if (node.type === 'JSXElement' || node.type === 'JSXFragment') {
585
- // Recurse through JSX children
586
- if (node.children && Array.isArray(node.children)) {
587
- node.children.forEach(function (child) { return findDataProvidersAndParents(child, node); });
644
+ if (node.children && Array.isArray(node.children)) {
645
+ for (var _i = 0, _c = node.children; _i < _c.length; _i++) {
646
+ var c = _c[_i];
647
+ var r = findRepeater(c);
648
+ if (r) {
649
+ return r;
650
+ }
588
651
  }
589
652
  }
590
- else if (node.type === 'JSXExpressionContainer') {
591
- // For expression containers, continue but don't go into the expression itself
592
- if (node.expression &&
593
- (node.expression.type === 'JSXElement' || node.expression.type === 'JSXFragment')) {
594
- findDataProvidersAndParents(node.expression, parent);
595
- }
653
+ return null;
654
+ };
655
+ var repeater = findRepeater(renderSuccessAttr.value.expression);
656
+ if (!repeater) {
657
+ return undefined;
658
+ }
659
+ var renderItemAttr = repeater.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'renderItem'; });
660
+ if (!((_e = (_d = (_c = (_b = renderItemAttr === null || renderItemAttr === void 0 ? void 0 : renderItemAttr.value) === null || _b === void 0 ? void 0 : _b.expression) === null || _c === void 0 ? void 0 : _c.params) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.name)) {
661
+ return undefined;
662
+ }
663
+ return renderItemAttr.value.expression.params[0].name;
664
+ }
665
+ function findAllSearchInputsInJSX(blockStatement) {
666
+ var results = [];
667
+ var traverse = function (node) {
668
+ var _a, _b, _c, _d, _e, _f;
669
+ if (!node) {
670
+ return;
596
671
  }
597
- else if (node.type === 'BlockStatement') {
598
- // For block statements (function bodies), look through body array
599
- if (node.body && Array.isArray(node.body)) {
600
- node.body.forEach(function (stmt) { return findDataProvidersAndParents(stmt, node); });
672
+ 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') {
673
+ var classAttr = (_c = node.openingElement.attributes) === null || _c === void 0 ? void 0 : _c.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'className'; });
674
+ 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) || '';
675
+ if (className.includes('search-input')) {
676
+ results.push({ node: node, className: className });
601
677
  }
602
678
  }
603
- else if (node.type === 'ConditionalExpression') {
604
- // Check both branches of conditional
605
- findDataProvidersAndParents(node.consequent, parent);
606
- findDataProvidersAndParents(node.alternate, parent);
679
+ if (node.children && Array.isArray(node.children)) {
680
+ node.children.forEach(function (c) { return traverse(c); });
607
681
  }
608
- };
609
- findDataProvidersAndParents(blockStatement);
610
- // Now process each DataProvider and find its siblings
611
- dataProvidersWithParents.forEach(function (_a) {
612
- var _b, _c;
613
- var dataProvider = _a.dataProvider, parent = _a.parent;
614
- var nameAttr = dataProvider.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'name'; });
615
- // Find the array mapper render prop by looking inside renderSuccess -> Repeater -> renderItem param
616
- var renderSuccessAttr = dataProvider.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'renderSuccess'; });
617
- var arrayMapperRenderProp;
618
- if (renderSuccessAttr && ((_b = renderSuccessAttr.value) === null || _b === void 0 ? void 0 : _b.type) === 'JSXExpressionContainer') {
619
- var renderFunc = renderSuccessAttr.value.expression;
620
- if (renderFunc.type === 'ArrowFunctionExpression') {
621
- // Look for Repeater inside the render function
622
- var findRepeater_1 = function (node) {
623
- var _a, _b;
624
- if (!node) {
625
- return null;
626
- }
627
- if (node.type === 'JSXElement' && ((_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.name) === 'Repeater') {
628
- return node;
629
- }
630
- if (node.body) {
631
- return findRepeater_1(node.body);
632
- }
633
- if (node.children && Array.isArray(node.children)) {
634
- for (var _i = 0, _c = node.children; _i < _c.length; _i++) {
635
- var child = _c[_i];
636
- var result = findRepeater_1(child);
637
- if (result) {
638
- return result;
639
- }
640
- }
641
- }
642
- if (node.type === 'JSXFragment' || node.type === 'JSXElement') {
643
- if (node.children && Array.isArray(node.children)) {
644
- for (var _d = 0, _e = node.children; _d < _e.length; _d++) {
645
- var child = _e[_d];
646
- var result = findRepeater_1(child);
647
- if (result) {
648
- return result;
649
- }
650
- }
651
- }
652
- }
653
- if (node.type === 'JSXExpressionContainer') {
654
- return findRepeater_1(node.expression);
655
- }
656
- if (node.expression) {
657
- return findRepeater_1(node.expression);
658
- }
659
- if (node.consequent) {
660
- var result = findRepeater_1(node.consequent);
661
- if (result) {
662
- return result;
663
- }
664
- }
665
- if (node.alternate) {
666
- return findRepeater_1(node.alternate);
667
- }
668
- return null;
669
- };
670
- var repeater = findRepeater_1(renderFunc);
671
- if (repeater) {
672
- // Find renderItem attribute on Repeater
673
- var renderItemAttr = repeater.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'renderItem'; });
674
- if (renderItemAttr && ((_c = renderItemAttr.value) === null || _c === void 0 ? void 0 : _c.type) === 'JSXExpressionContainer') {
675
- var renderItemFunc = renderItemAttr.value.expression;
676
- if (renderItemFunc.type === 'ArrowFunctionExpression' &&
677
- renderItemFunc.params &&
678
- renderItemFunc.params.length > 0) {
679
- var param = renderItemFunc.params[0];
680
- if (param.type === 'Identifier') {
681
- arrayMapperRenderProp = param.name;
682
- }
683
- }
684
- }
685
- }
682
+ if (node.body) {
683
+ if (Array.isArray(node.body)) {
684
+ node.body.forEach(function (s) { return traverse(s); });
685
+ }
686
+ else {
687
+ traverse(node.body);
686
688
  }
687
689
  }
688
- if (!nameAttr ||
689
- !nameAttr.value ||
690
- nameAttr.value.type !== 'JSXExpressionContainer' ||
691
- !arrayMapperRenderProp) {
690
+ if (node.consequent) {
691
+ traverse(node.consequent);
692
+ }
693
+ if (node.alternate) {
694
+ traverse(node.alternate);
695
+ }
696
+ if (node.expression) {
697
+ traverse(node.expression);
698
+ }
699
+ if (node.argument) {
700
+ traverse(node.argument);
701
+ }
702
+ };
703
+ traverse(blockStatement);
704
+ return results;
705
+ }
706
+ function findAllPaginationNodesInJSX(blockStatement) {
707
+ var results = [];
708
+ var traverse = function (node) {
709
+ var _a, _b, _c, _d, _e;
710
+ if (!node) {
692
711
  return;
693
712
  }
694
- var dataProviderIdentifier = nameAttr.value.expression.value;
695
- var paginationNodeInfo = null;
696
- var searchInputInfo = null;
697
- var findSearchAndPaginationInScope = function (scopeNode, skipNode) {
698
- var _a, _b, _c, _d, _e, _f;
699
- if (skipNode === void 0) { skipNode = null; }
700
- if (!scopeNode || !scopeNode.children || !Array.isArray(scopeNode.children)) {
701
- return false;
713
+ if (node.type === 'JSXElement') {
714
+ var classAttr = (_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.attributes) === null || _b === void 0 ? void 0 : _b.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'className'; });
715
+ var className = ((_c = classAttr === null || classAttr === void 0 ? void 0 : classAttr.value) === null || _c === void 0 ? void 0 : _c.value) || ((_e = (_d = classAttr === null || classAttr === void 0 ? void 0 : classAttr.value) === null || _d === void 0 ? void 0 : _d.expression) === null || _e === void 0 ? void 0 : _e.value) || '';
716
+ if (className.includes('cms-pagination-node')) {
717
+ results.push({ node: node, className: className });
702
718
  }
703
- var foundSomething = false;
704
- for (var _i = 0, _g = scopeNode.children; _i < _g.length; _i++) {
705
- var child = _g[_i];
706
- if (child === skipNode) {
707
- continue;
708
- }
709
- if (child.type === 'JSXElement') {
710
- var childClassName = getClassName(((_a = child.openingElement) === null || _a === void 0 ? void 0 : _a.attributes) || []);
711
- var childElementName = (_c = (_b = child.openingElement) === null || _b === void 0 ? void 0 : _b.name) === null || _c === void 0 ? void 0 : _c.name;
712
- // Found pagination node
713
- if (childClassName && childClassName.includes('cms-pagination-node')) {
714
- var prevClass = findChildWithClass(child, 'previous');
715
- var nextClass = findChildWithClass(child, 'next');
716
- if (prevClass || nextClass) {
717
- paginationNodeInfo = {
718
- class: childClassName,
719
- prevClass: prevClass,
720
- nextClass: nextClass,
721
- };
722
- foundSomething = true;
723
- }
724
- }
725
- // Found search container - search for input inside it
726
- if (childClassName && childClassName.includes('data-source-search-node')) {
727
- if (child.children && Array.isArray(child.children)) {
728
- for (var _h = 0, _j = child.children; _h < _j.length; _h++) {
729
- var searchChild = _j[_h];
730
- if (searchChild.type === 'JSXElement') {
731
- var searchChildElementName = (_e = (_d = searchChild.openingElement) === null || _d === void 0 ? void 0 : _d.name) === null || _e === void 0 ? void 0 : _e.name;
732
- var searchChildClassName = getClassName(((_f = searchChild.openingElement) === null || _f === void 0 ? void 0 : _f.attributes) || []);
733
- if (searchChildClassName &&
734
- searchChildClassName.includes('search-input') &&
735
- searchChildElementName === 'input') {
736
- searchInputInfo = {
737
- class: searchChildClassName,
738
- jsx: searchChild,
739
- };
740
- foundSomething = true;
741
- }
742
- }
743
- }
744
- }
745
- }
746
- // Also check if search input is a direct child
747
- if (childClassName &&
748
- childClassName.includes('search-input') &&
749
- childElementName === 'input') {
750
- searchInputInfo = {
751
- class: childClassName,
752
- jsx: child,
753
- };
754
- foundSomething = true;
755
- }
756
- // Stop searching if we found both or if we found what we're looking for
757
- if (foundSomething && (searchInputInfo || paginationNodeInfo)) {
758
- return true;
759
- }
760
- // Only recurse if we haven't found what we're looking for yet
761
- if (!searchInputInfo || !paginationNodeInfo) {
762
- if (findSearchAndPaginationInScope(child, skipNode)) {
763
- return true;
764
- }
765
- }
766
- }
719
+ }
720
+ if (node.children && Array.isArray(node.children)) {
721
+ node.children.forEach(function (c) { return traverse(c); });
722
+ }
723
+ if (node.body) {
724
+ if (Array.isArray(node.body)) {
725
+ node.body.forEach(function (s) { return traverse(s); });
767
726
  }
768
- return foundSomething;
769
- };
770
- var currentScope = parent;
771
- var depth = 0;
772
- var maxDepth = 5;
773
- while (currentScope && (!searchInputInfo || !paginationNodeInfo) && depth < maxDepth) {
774
- var found = findSearchAndPaginationInScope(currentScope, depth === 0 ? dataProvider : null);
775
- // Stop searching up the tree if we found a pagination node at this level
776
- if (found && paginationNodeInfo) {
777
- break;
727
+ else {
728
+ traverse(node.body);
778
729
  }
779
- currentScope = findParentNode(blockStatement, currentScope);
780
- depth++;
781
730
  }
782
- // Record the DataProvider with its pagination/search info
783
- // Use array instead of Map to handle multiple DataProviders with same name
784
- dataProviderList.push({
785
- identifier: dataProviderIdentifier,
786
- dataProvider: dataProvider,
787
- arrayMapperRenderProp: arrayMapperRenderProp,
788
- paginationNode: paginationNodeInfo || undefined,
789
- searchInput: searchInputInfo || undefined,
790
- hasPagination: !!paginationNodeInfo,
791
- hasSearch: !!searchInputInfo,
792
- });
793
- });
794
- // Categorize data providers
795
- var paginatedMappers = [];
796
- var searchOnlyMappers = [];
797
- var paginationOnlyMappers = [];
798
- var plainMappers = [];
799
- dataProviderList.forEach(function (info) {
800
- var _a, _b, _c, _d;
801
- // Check UIDL flags for this array mapper
802
- var uidlInfo = info.arrayMapperRenderProp
803
- ? arrayMapperInfoMap.get(info.arrayMapperRenderProp)
804
- : null;
805
- // Only process pagination/search if UIDL explicitly enables it
806
- var shouldHavePagination = (uidlInfo === null || uidlInfo === void 0 ? void 0 : uidlInfo.paginated) && info.hasPagination;
807
- var shouldHaveSearch = (uidlInfo === null || uidlInfo === void 0 ? void 0 : uidlInfo.searchEnabled) && info.hasSearch;
808
- if (shouldHavePagination && shouldHaveSearch) {
809
- // Pagination + Search
810
- paginatedMappers.push({
811
- paginationNodeClass: info.paginationNode.class,
812
- prevButtonClass: info.paginationNode.prevClass,
813
- nextButtonClass: info.paginationNode.nextClass,
814
- dataSourceIdentifier: info.identifier,
815
- dataProviderJSX: info.dataProvider,
816
- arrayMapperRenderProp: info.arrayMapperRenderProp,
817
- searchInputClass: (_a = info.searchInput) === null || _a === void 0 ? void 0 : _a.class,
818
- searchInputJSX: (_b = info.searchInput) === null || _b === void 0 ? void 0 : _b.jsx,
819
- });
731
+ if (node.consequent) {
732
+ traverse(node.consequent);
820
733
  }
821
- else if (shouldHavePagination && !shouldHaveSearch) {
822
- // Pagination only
823
- paginationOnlyMappers.push({
824
- paginationNodeClass: info.paginationNode.class,
825
- prevButtonClass: info.paginationNode.prevClass,
826
- nextButtonClass: info.paginationNode.nextClass,
827
- dataSourceIdentifier: info.identifier,
828
- dataProviderJSX: info.dataProvider,
829
- arrayMapperRenderProp: info.arrayMapperRenderProp,
830
- searchInputClass: undefined,
831
- searchInputJSX: undefined,
832
- });
734
+ if (node.alternate) {
735
+ traverse(node.alternate);
833
736
  }
834
- else if (!shouldHavePagination && shouldHaveSearch) {
835
- // Search only
836
- searchOnlyMappers.push({
837
- paginationNodeClass: '',
838
- prevButtonClass: null,
839
- nextButtonClass: null,
840
- dataSourceIdentifier: info.identifier,
841
- dataProviderJSX: info.dataProvider,
842
- arrayMapperRenderProp: info.arrayMapperRenderProp,
843
- searchInputClass: (_c = info.searchInput) === null || _c === void 0 ? void 0 : _c.class,
844
- searchInputJSX: (_d = info.searchInput) === null || _d === void 0 ? void 0 : _d.jsx,
845
- });
737
+ if (node.expression) {
738
+ traverse(node.expression);
846
739
  }
847
- else {
848
- // Plain (no pagination, no search) - UIDL doesn't enable it or no controls found
849
- plainMappers.push({
850
- paginationNodeClass: '',
851
- prevButtonClass: null,
852
- nextButtonClass: null,
853
- dataSourceIdentifier: info.identifier,
854
- dataProviderJSX: info.dataProvider,
855
- arrayMapperRenderProp: info.arrayMapperRenderProp,
856
- searchInputClass: undefined,
857
- searchInputJSX: undefined,
858
- });
740
+ if (node.argument) {
741
+ traverse(node.argument);
859
742
  }
860
- });
861
- return { paginatedMappers: paginatedMappers, searchOnlyMappers: searchOnlyMappers, paginationOnlyMappers: paginationOnlyMappers, plainMappers: plainMappers };
743
+ };
744
+ traverse(blockStatement);
745
+ return results;
862
746
  }
863
- function handleSearchOnlyArrayMappers(blockStatement, searchOnlyDataSources, searchConfigMap, queryColumnsMap, dependencies) {
864
- var searchOnlyStates = [];
865
- var searchOnlyEffects = [];
866
- searchOnlyDataSources.forEach(function (detected, index) {
867
- var searchId = "search_".concat(index);
868
- var searchQueryVar = "".concat(searchId, "_query");
869
- var setSearchQueryVar = "set".concat(searchQueryVar.charAt(0).toUpperCase() + searchQueryVar.slice(1));
870
- var debouncedSearchQueryVar = "debounced".concat(searchQueryVar.charAt(0).toUpperCase() + searchQueryVar.slice(1));
871
- var setDebouncedSearchQueryVar = "set".concat(debouncedSearchQueryVar.charAt(0).toUpperCase() + debouncedSearchQueryVar.slice(1));
872
- var skipDebounceOnMountRefVar = "skipDebounceOnMount".concat(searchId);
873
- var searchConfig = searchConfigMap.get(detected.dataSourceIdentifier);
874
- var searchDebounce = (searchConfig === null || searchConfig === void 0 ? void 0 : searchConfig.searchDebounce) || 300;
875
- var queryColumns = queryColumnsMap.get(detected.dataSourceIdentifier);
876
- // Add skip ref
877
- var skipRefAST = types.variableDeclaration('const', [
878
- types.variableDeclarator(types.identifier(skipDebounceOnMountRefVar), types.callExpression(types.identifier('useRef'), [types.booleanLiteral(true)])),
879
- ]);
880
- searchOnlyStates.push(skipRefAST);
881
- // Add debounced search state
882
- var debouncedSearchStateAST = types.variableDeclaration('const', [
883
- types.variableDeclarator(types.arrayPattern([
884
- types.identifier(debouncedSearchQueryVar),
885
- types.identifier(setDebouncedSearchQueryVar),
886
- ]), types.callExpression(types.identifier('useState'), [types.stringLiteral('')])),
887
- ]);
888
- searchOnlyStates.push(debouncedSearchStateAST);
889
- // Add search query state
890
- var searchStateAST = types.variableDeclaration('const', [
891
- types.variableDeclarator(types.arrayPattern([types.identifier(searchQueryVar), types.identifier(setSearchQueryVar)]), types.callExpression(types.identifier('useState'), [types.stringLiteral('')])),
892
- ]);
893
- searchOnlyStates.push(searchStateAST);
894
- // Add useEffect for debouncing
895
- if (!dependencies.useEffect) {
896
- dependencies.useEffect = {
897
- type: 'library',
898
- path: 'react',
899
- version: '',
900
- meta: {
901
- namedImport: true,
902
- },
903
- };
904
- }
905
- var debounceEffect = types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
906
- types.arrowFunctionExpression([], types.blockStatement([
907
- types.ifStatement(types.memberExpression(types.identifier(skipDebounceOnMountRefVar), types.identifier('current')), types.blockStatement([
908
- types.expressionStatement(types.assignmentExpression('=', types.memberExpression(types.identifier(skipDebounceOnMountRefVar), types.identifier('current')), types.booleanLiteral(false))),
909
- types.returnStatement(),
910
- ])),
911
- types.variableDeclaration('const', [
912
- types.variableDeclarator(types.identifier('timer'), types.callExpression(types.identifier('setTimeout'), [
913
- types.arrowFunctionExpression([], types.blockStatement([
914
- types.expressionStatement(types.callExpression(types.identifier(setDebouncedSearchQueryVar), [
915
- types.identifier(searchQueryVar),
916
- ])),
917
- ])),
918
- types.numericLiteral(searchDebounce),
919
- ])),
920
- ]),
921
- types.returnStatement(types.arrowFunctionExpression([], types.callExpression(types.identifier('clearTimeout'), [types.identifier('timer')]))),
922
- ])),
923
- types.arrayExpression([types.identifier(searchQueryVar)]),
924
- ]));
925
- searchOnlyEffects.push(debounceEffect);
926
- // Modify DataProvider to include search params (even without queryColumns)
927
- if (detected.dataProviderJSX) {
928
- addSearchParamsToDataProvider(detected.dataProviderJSX, {
929
- debouncedSearchQueryVar: debouncedSearchQueryVar,
930
- queryColumns: queryColumns || [],
931
- });
932
- }
933
- // Modify search input
934
- if (detected.searchInputJSX) {
935
- addSearchInputHandlers(detected.searchInputJSX, {
936
- searchQueryVar: searchQueryVar,
937
- setSearchQueryVar: setSearchQueryVar,
938
- searchEnabled: true,
939
- });
940
- }
941
- });
942
- // Add all state declarations at the beginning in correct order
943
- searchOnlyStates.reverse().forEach(function (stateDecl) {
944
- blockStatement.body.unshift(stateDecl);
747
+ function updateDataProviderForPaginatedSearch(dp, usage, vars, fileName) {
748
+ var attrs = dp.openingElement.attributes;
749
+ // Remove existing params, key, initialData, fetchData, persistDataDuringLoading
750
+ dp.openingElement.attributes = attrs.filter(function (attr) {
751
+ var _a;
752
+ return !['params', 'key', 'initialData', 'fetchData', 'persistDataDuringLoading'].includes((_a = attr.name) === null || _a === void 0 ? void 0 : _a.name);
945
753
  });
946
- // Recalculate insertIndex after adding states (since unshift shifted everything)
947
- var newInsertIndex = blockStatement.body.findIndex(function (stmt) { return stmt.type === 'ReturnStatement'; });
948
- var finalInsertIndex = newInsertIndex !== -1 ? newInsertIndex : blockStatement.body.length;
949
- // Add all useEffect hooks before the return statement
950
- searchOnlyEffects.reverse().forEach(function (effect) {
951
- blockStatement.body.splice(finalInsertIndex, 0, effect);
754
+ // Add params with useMemo
755
+ var paramsProps = [
756
+ types.objectProperty(types.identifier('page'), types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('page'))),
757
+ types.objectProperty(types.identifier('perPage'), types.numericLiteral(usage.perPage)),
758
+ types.objectProperty(types.identifier('query'), types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('debouncedQuery'))),
759
+ ];
760
+ if (usage.queryColumns.length > 0) {
761
+ paramsProps.push(types.objectProperty(types.identifier('queryColumns'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [types.arrayExpression(usage.queryColumns.map(function (c) { return types.stringLiteral(c); }))])));
762
+ }
763
+ dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('params'), types.jsxExpressionContainer(types.callExpression(types.identifier('useMemo'), [
764
+ types.arrowFunctionExpression([], types.objectExpression(paramsProps)),
765
+ types.arrayExpression([types.identifier(vars.combinedStateVar)]),
766
+ ]))));
767
+ // Add initialData
768
+ var initialDataCondition = 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));
769
+ 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), types.identifier('undefined')))));
770
+ // Add key
771
+ dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(types.templateLiteral([
772
+ types.templateElement({
773
+ raw: "".concat(usage.dataSourceIdentifier, "-"),
774
+ cooked: "".concat(usage.dataSourceIdentifier, "-"),
775
+ }),
776
+ types.templateElement({ raw: '-', cooked: '-' }),
777
+ types.templateElement({ raw: '', cooked: '' }),
778
+ ], [
779
+ types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('page')),
780
+ types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('debouncedQuery')),
781
+ ]))));
782
+ // Add fetchData
783
+ dp.openingElement.attributes.push(createFetchDataAttribute(fileName));
784
+ // Add persistDataDuringLoading
785
+ dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('persistDataDuringLoading'), types.jsxExpressionContainer(types.booleanLiteral(true))));
786
+ }
787
+ function updateDataProviderForPaginationOnly(dp, usage, vars, fileName) {
788
+ var attrs = dp.openingElement.attributes;
789
+ dp.openingElement.attributes = attrs.filter(function (attr) {
790
+ var _a;
791
+ return !['params', 'key', 'initialData', 'fetchData', 'persistDataDuringLoading'].includes((_a = attr.name) === null || _a === void 0 ? void 0 : _a.name);
952
792
  });
793
+ // Add params
794
+ dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('params'), types.jsxExpressionContainer(types.callExpression(types.identifier('useMemo'), [
795
+ types.arrowFunctionExpression([], types.objectExpression([
796
+ types.objectProperty(types.identifier('page'), types.identifier(vars.pageStateVar)),
797
+ types.objectProperty(types.identifier('perPage'), types.numericLiteral(usage.perPage)),
798
+ ])),
799
+ types.arrayExpression([types.identifier(vars.pageStateVar)]),
800
+ ]))));
801
+ // Add initialData
802
+ dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.conditionalExpression(types.binaryExpression('===', types.identifier(vars.pageStateVar), types.numericLiteral(1)), types.optionalMemberExpression(types.identifier('props'), types.identifier(vars.propsPrefix), false, true), types.identifier('undefined')))));
803
+ // Add key
804
+ dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(types.templateLiteral([
805
+ types.templateElement({
806
+ raw: "".concat(usage.dataSourceIdentifier, "-page-"),
807
+ cooked: "".concat(usage.dataSourceIdentifier, "-page-"),
808
+ }),
809
+ types.templateElement({ raw: '', cooked: '' }),
810
+ ], [types.identifier(vars.pageStateVar)]))));
811
+ // Add fetchData
812
+ dp.openingElement.attributes.push(createFetchDataAttribute(fileName));
813
+ dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('persistDataDuringLoading'), types.jsxExpressionContainer(types.booleanLiteral(true))));
953
814
  }
954
- function addSearchParamsToDataProvider(dataProviderJSX, config) {
955
- var _a, _b;
956
- if (!dataProviderJSX || !dataProviderJSX.openingElement) {
957
- return;
958
- }
959
- var debouncedSearchQueryVar = config.debouncedSearchQueryVar, queryColumns = config.queryColumns;
960
- // 1. Update params to be wrapped in useMemo
961
- var existingParamsAttr = dataProviderJSX.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'params'; });
962
- if (existingParamsAttr && ((_a = existingParamsAttr.value) === null || _a === void 0 ? void 0 : _a.type) === 'JSXExpressionContainer') {
963
- var paramsObj = existingParamsAttr.value.expression;
964
- if (paramsObj.type === 'ObjectExpression') {
965
- // Add query to existing params properties
966
- paramsObj.properties.push(types.objectProperty(types.identifier('query'), types.identifier(debouncedSearchQueryVar)));
967
- // Add queryColumns only if they exist
968
- if (queryColumns.length > 0) {
969
- paramsObj.properties.push(types.objectProperty(types.identifier('queryColumns'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [types.arrayExpression(queryColumns.map(function (col) { return types.stringLiteral(col); }))])));
970
- }
971
- // Wrap in useMemo with debouncedSearchQueryVar as dependency
972
- var memoizedParamsValue = types.callExpression(types.identifier('useMemo'), [
973
- types.arrowFunctionExpression([], paramsObj),
974
- types.arrayExpression([types.identifier(debouncedSearchQueryVar)]),
975
- ]);
976
- existingParamsAttr.value.expression = memoizedParamsValue;
977
- }
978
- }
979
- // 2. Update initialData to be conditional on empty search
980
- var existingInitialDataAttr = dataProviderJSX.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'initialData'; });
981
- if (existingInitialDataAttr && ((_b = existingInitialDataAttr.value) === null || _b === void 0 ? void 0 : _b.type) === 'JSXExpressionContainer') {
982
- var currentInitialData = existingInitialDataAttr.value.expression;
983
- // Make it conditional: only use initialData if search is empty
984
- existingInitialDataAttr.value.expression = types.conditionalExpression(types.unaryExpression('!', types.identifier(debouncedSearchQueryVar), true), currentInitialData, types.identifier('undefined'));
815
+ function updateDataProviderForSearchOnly(dp, usage, vars, fileName) {
816
+ var attrs = dp.openingElement.attributes;
817
+ dp.openingElement.attributes = attrs.filter(function (attr) {
818
+ var _a;
819
+ return !['params', 'key', 'initialData', 'fetchData', 'persistDataDuringLoading'].includes((_a = attr.name) === null || _a === void 0 ? void 0 : _a.name);
820
+ });
821
+ // Add params
822
+ var paramsProps = [
823
+ types.objectProperty(types.identifier('query'), types.identifier(vars.debouncedSearchQueryVar)),
824
+ ];
825
+ if (usage.queryColumns.length > 0) {
826
+ paramsProps.push(types.objectProperty(types.identifier('queryColumns'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [types.arrayExpression(usage.queryColumns.map(function (c) { return types.stringLiteral(c); }))])));
985
827
  }
986
- // 3. Update key to include search query
987
- var existingKeyAttr = dataProviderJSX.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'key'; });
988
- var keyExpression = types.templateLiteral([
828
+ dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('params'), types.jsxExpressionContainer(types.callExpression(types.identifier('useMemo'), [
829
+ types.arrowFunctionExpression([], types.objectExpression(paramsProps)),
830
+ types.arrayExpression([types.identifier(vars.debouncedSearchQueryVar)]),
831
+ ]))));
832
+ // Add initialData
833
+ dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.conditionalExpression(types.unaryExpression('!', types.identifier(vars.debouncedSearchQueryVar), true), types.optionalMemberExpression(types.identifier('props'), types.identifier(vars.propsPrefix), false, true), types.identifier('undefined')))));
834
+ // Add key
835
+ dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(types.templateLiteral([
989
836
  types.templateElement({ raw: 'search-', cooked: 'search-' }),
990
837
  types.templateElement({ raw: '', cooked: '' }),
991
- ], [types.identifier(debouncedSearchQueryVar)]);
992
- var keyAttr = types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(keyExpression));
993
- if (existingKeyAttr) {
994
- var index = dataProviderJSX.openingElement.attributes.indexOf(existingKeyAttr);
995
- dataProviderJSX.openingElement.attributes[index] = keyAttr;
996
- }
997
- else {
998
- dataProviderJSX.openingElement.attributes.push(keyAttr);
838
+ ], [types.identifier(vars.debouncedSearchQueryVar)]))));
839
+ // Add fetchData
840
+ dp.openingElement.attributes.push(createFetchDataAttribute(fileName));
841
+ dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('persistDataDuringLoading'), types.jsxExpressionContainer(types.booleanLiteral(true))));
842
+ }
843
+ function updateDataProviderForPlain(dp, vars) {
844
+ var attrs = dp.openingElement.attributes;
845
+ // Remove params and fetchData - plain mappers only use initialData
846
+ dp.openingElement.attributes = attrs.filter(function (attr) { var _a; return !['params', 'fetchData'].includes((_a = attr.name) === null || _a === void 0 ? void 0 : _a.name); });
847
+ // Update initialData to use correct prop
848
+ var existingInitialData = dp.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'initialData'; });
849
+ if (existingInitialData) {
850
+ existingInitialData.value = types.jsxExpressionContainer(types.optionalMemberExpression(types.identifier('props'), types.identifier(vars.propsPrefix), false, true));
999
851
  }
1000
852
  }
1001
- function addPaginationParamsToDataProvider(dataProviderJSX, info, paginationIndex) {
1002
- var _a;
1003
- if (!dataProviderJSX || !dataProviderJSX.openingElement) {
853
+ function stabilizeDataProviderWithoutRepeater(dp) {
854
+ var _a, _b, _c;
855
+ var attrs = dp.openingElement.attributes;
856
+ // Find the params attribute
857
+ var paramsAttrIndex = attrs.findIndex(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'params'; });
858
+ if (paramsAttrIndex === -1) {
1004
859
  return;
1005
860
  }
1006
- var combinedStateVar = info.combinedStateVar;
1007
- var paramsProperties;
1008
- var dependencies;
1009
- if (info.searchEnabled && combinedStateVar) {
1010
- // Use combined state for both page and query
1011
- paramsProperties = [
1012
- types.objectProperty(types.identifier('page'), types.memberExpression(types.identifier(combinedStateVar), types.identifier('page'))),
1013
- types.objectProperty(types.identifier('perPage'), types.numericLiteral(info.perPage)),
1014
- types.objectProperty(types.identifier('query'), types.memberExpression(types.identifier(combinedStateVar), types.identifier('debouncedQuery'))),
1015
- ];
1016
- if (info.queryColumns && info.queryColumns.length > 0) {
1017
- paramsProperties.push(types.objectProperty(types.identifier('queryColumns'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [types.arrayExpression(info.queryColumns.map(function (col) { return types.stringLiteral(col); }))])));
1018
- }
1019
- // Single dependency: the combined state object
1020
- dependencies = [types.identifier(combinedStateVar)];
1021
- }
1022
- else {
1023
- // Pagination only (no search)
1024
- paramsProperties = [
1025
- types.objectProperty(types.identifier('page'), types.identifier(info.pageStateVar)),
1026
- types.objectProperty(types.identifier('perPage'), types.numericLiteral(info.perPage)),
1027
- ];
1028
- dependencies = [types.identifier(info.pageStateVar)];
1029
- }
1030
- // Wrap params in useMemo to prevent unnecessary refetches
1031
- var memoizedParamsValue = types.callExpression(types.identifier('useMemo'), [
1032
- types.arrowFunctionExpression([], types.objectExpression(paramsProperties)),
1033
- types.arrayExpression(dependencies),
1034
- ]);
1035
- var paramsAttr = types.jsxAttribute(types.jsxIdentifier('params'), types.jsxExpressionContainer(memoizedParamsValue));
1036
- var existingParamsAttr = dataProviderJSX.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'params'; });
1037
- if (existingParamsAttr) {
1038
- var index = dataProviderJSX.openingElement.attributes.indexOf(existingParamsAttr);
1039
- dataProviderJSX.openingElement.attributes[index] = paramsAttr;
1040
- }
1041
- else {
1042
- dataProviderJSX.openingElement.attributes.push(paramsAttr);
1043
- }
1044
- var existingInitialDataAttr = dataProviderJSX.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'initialData'; });
1045
- if (existingInitialDataAttr && existingInitialDataAttr.value) {
1046
- // Update initialData to use the paginated prop name
1047
- var paginatedPropName = "".concat(info.dataSourceIdentifier, "_pg_").concat(paginationIndex);
1048
- // If search is enabled, use combined state; otherwise use page state
1049
- var condition = void 0;
1050
- if (info.searchEnabled && combinedStateVar) {
1051
- condition = types.logicalExpression('&&', types.binaryExpression('===', types.memberExpression(types.identifier(combinedStateVar), types.identifier('page')), types.numericLiteral(1)), types.unaryExpression('!', types.memberExpression(types.identifier(combinedStateVar), types.identifier('debouncedQuery')), true));
1052
- }
1053
- else {
1054
- condition = types.binaryExpression('===', types.identifier(info.pageStateVar), types.numericLiteral(1));
1055
- }
1056
- existingInitialDataAttr.value.expression = types.conditionalExpression(condition, types.optionalMemberExpression(types.identifier('props'), types.identifier(paginatedPropName), false, true), types.identifier('undefined'));
1057
- }
1058
- var existingKeyAttr = dataProviderJSX.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'key'; });
1059
- // Include page and search in key to trigger refetch when they change
1060
- var keyExpression;
1061
- if (info.searchEnabled && combinedStateVar) {
1062
- keyExpression = types.templateLiteral([
1063
- types.templateElement({
1064
- raw: "".concat(info.dataSourceIdentifier, "-page-"),
1065
- cooked: "".concat(info.dataSourceIdentifier, "-page-"),
1066
- }),
1067
- types.templateElement({ raw: '-search-', cooked: '-search-' }),
1068
- types.templateElement({ raw: '', cooked: '' }),
1069
- ], [
1070
- types.memberExpression(types.identifier(combinedStateVar), types.identifier('page')),
1071
- types.memberExpression(types.identifier(combinedStateVar), types.identifier('debouncedQuery')),
1072
- ]);
1073
- }
1074
- else {
1075
- keyExpression = types.templateLiteral([
1076
- types.templateElement({
1077
- raw: "".concat(info.dataSourceIdentifier, "-"),
1078
- cooked: "".concat(info.dataSourceIdentifier, "-"),
1079
- }),
1080
- types.templateElement({ raw: '', cooked: '' }),
1081
- ], [types.identifier(info.pageStateVar)]);
1082
- }
1083
- var keyAttr = types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(keyExpression));
1084
- if (existingKeyAttr) {
1085
- var index = dataProviderJSX.openingElement.attributes.indexOf(existingKeyAttr);
1086
- dataProviderJSX.openingElement.attributes[index] = keyAttr;
861
+ var paramsAttr = attrs[paramsAttrIndex];
862
+ // Check if params is already wrapped in useMemo
863
+ if (((_a = paramsAttr.value) === null || _a === void 0 ? void 0 : _a.type) === 'JSXExpressionContainer' &&
864
+ paramsAttr.value.expression.type === 'CallExpression' &&
865
+ ((_b = paramsAttr.value.expression.callee) === null || _b === void 0 ? void 0 : _b.name) === 'useMemo') {
866
+ return;
1087
867
  }
1088
- else {
1089
- dataProviderJSX.openingElement.attributes.push(keyAttr);
868
+ // Get the current params value expression
869
+ var paramsExpression = null;
870
+ if (((_c = paramsAttr.value) === null || _c === void 0 ? void 0 : _c.type) === 'JSXExpressionContainer') {
871
+ paramsExpression = paramsAttr.value.expression;
1090
872
  }
1091
- // For pagination, always create a fresh fetchData that calls the API route
1092
- // Get the resource definition to build the API URL
1093
- var resourceDefAttr = dataProviderJSX.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'resourceDefinition'; });
1094
- if (resourceDefAttr && ((_a = resourceDefAttr.value) === null || _a === void 0 ? void 0 : _a.type) === 'JSXExpressionContainer') {
1095
- var resourceDef = resourceDefAttr.value.expression;
1096
- if (resourceDef.type === 'ObjectExpression') {
1097
- var dataSourceIdProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'dataSourceId'; });
1098
- var tableNameProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'tableName'; });
1099
- var dataSourceTypeProp = resourceDef.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.value === 'dataSourceType'; });
1100
- if (dataSourceIdProp && tableNameProp && dataSourceTypeProp) {
1101
- var dataSourceId = dataSourceIdProp.value.value;
1102
- var tableName = tableNameProp.value.value;
1103
- var dataSourceType = dataSourceTypeProp.value.value;
1104
- var fileName = "".concat(dataSourceType, "-").concat(tableName, "-").concat(dataSourceId.substring(0, 8));
1105
- // Create fetchData attribute with proper fetch chain wrapped in useCallback
1106
- var fetchDataValue = types.callExpression(types.identifier('useCallback'), [
1107
- types.arrowFunctionExpression([types.identifier('params')], types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.callExpression(types.identifier('fetch'), [
1108
- types.templateLiteral([
1109
- types.templateElement({
1110
- raw: "/api/".concat(fileName, "?"),
1111
- cooked: "/api/".concat(fileName, "?"),
1112
- }),
1113
- types.templateElement({ raw: '', cooked: '' }),
1114
- ], [
1115
- types.newExpression(types.identifier('URLSearchParams'), [
1116
- types.identifier('params'),
1117
- ]),
1118
- ]),
1119
- types.objectExpression([
1120
- types.objectProperty(types.identifier('headers'), types.objectExpression([
1121
- types.objectProperty(types.stringLiteral('Content-Type'), types.stringLiteral('application/json')),
1122
- ])),
1123
- ]),
1124
- ]), types.identifier('then')), [
1125
- types.arrowFunctionExpression([types.identifier('res')], types.callExpression(types.memberExpression(types.identifier('res'), types.identifier('json')), [])),
1126
- ]), types.identifier('then')), [
1127
- types.arrowFunctionExpression([types.identifier('response')], types.optionalMemberExpression(types.identifier('response'), types.identifier('data'), false, true)),
1128
- ])),
1129
- types.arrayExpression([]),
1130
- ]);
1131
- var newFetchDataAttr = types.jsxAttribute(types.jsxIdentifier('fetchData'), types.jsxExpressionContainer(fetchDataValue));
1132
- // Remove existing fetchData attribute if present
1133
- var existingFetchDataIndex = dataProviderJSX.openingElement.attributes.findIndex(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'fetchData'; });
1134
- if (existingFetchDataIndex !== -1) {
1135
- dataProviderJSX.openingElement.attributes[existingFetchDataIndex] = newFetchDataAttr;
1136
- }
1137
- else {
1138
- dataProviderJSX.openingElement.attributes.push(newFetchDataAttr);
1139
- }
1140
- }
1141
- }
873
+ if (!paramsExpression) {
874
+ return;
1142
875
  }
876
+ // Wrap params in useMemo with empty dependencies array
877
+ // This ensures the object reference stays stable across re-renders
878
+ var memoizedParams = types.callExpression(types.identifier('useMemo'), [
879
+ types.arrowFunctionExpression([], paramsExpression),
880
+ types.arrayExpression([]),
881
+ ]);
882
+ // Replace the params attribute
883
+ attrs[paramsAttrIndex] = types.jsxAttribute(types.jsxIdentifier('params'), types.jsxExpressionContainer(memoizedParams));
1143
884
  }
1144
- function findChildWithClass(node, classSubstring) {
1145
- var _a;
1146
- if (!node) {
1147
- return null;
1148
- }
1149
- if (node.type === 'JSXElement') {
1150
- var className = getClassName(((_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.attributes) || []);
1151
- if (className && className.includes(classSubstring)) {
1152
- return className;
1153
- }
1154
- }
1155
- if (node.children) {
1156
- for (var _i = 0, _b = node.children; _i < _b.length; _i++) {
1157
- var child = _b[_i];
1158
- var found = findChildWithClass(child, classSubstring);
1159
- if (found) {
1160
- return found;
1161
- }
1162
- }
1163
- }
1164
- if (typeof node === 'object') {
1165
- for (var _c = 0, _d = Object.values(node); _c < _d.length; _c++) {
1166
- var value = _d[_c];
1167
- if (Array.isArray(value)) {
1168
- for (var _e = 0, value_1 = value; _e < value_1.length; _e++) {
1169
- var item = value_1[_e];
1170
- var found = findChildWithClass(item, classSubstring);
1171
- if (found) {
1172
- return found;
1173
- }
1174
- }
1175
- }
1176
- else if (typeof value === 'object') {
1177
- var found = findChildWithClass(value, classSubstring);
1178
- if (found) {
1179
- return found;
1180
- }
1181
- }
1182
- }
1183
- }
1184
- return null;
885
+ function createFetchDataAttribute(fileName) {
886
+ return types.jsxAttribute(types.jsxIdentifier('fetchData'), types.jsxExpressionContainer(types.callExpression(types.identifier('useCallback'), [
887
+ types.arrowFunctionExpression([types.identifier('params')], types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.callExpression(types.identifier('fetch'), [
888
+ types.templateLiteral([
889
+ types.templateElement({
890
+ raw: "/api/".concat(fileName, "?"),
891
+ cooked: "/api/".concat(fileName, "?"),
892
+ }),
893
+ types.templateElement({ raw: '', cooked: '' }),
894
+ ], [
895
+ types.newExpression(types.identifier('URLSearchParams'), [
896
+ types.identifier('params'),
897
+ ]),
898
+ ]),
899
+ types.objectExpression([
900
+ types.objectProperty(types.identifier('headers'), types.objectExpression([
901
+ types.objectProperty(types.stringLiteral('Content-Type'), types.stringLiteral('application/json')),
902
+ ])),
903
+ ]),
904
+ ]), types.identifier('then')), [
905
+ types.arrowFunctionExpression([types.identifier('res')], types.callExpression(types.memberExpression(types.identifier('res'), types.identifier('json')), [])),
906
+ ]), types.identifier('then')), [
907
+ types.arrowFunctionExpression([types.identifier('response')], types.optionalMemberExpression(types.identifier('response'), types.identifier('data'), false, true)),
908
+ ])),
909
+ types.arrayExpression([]),
910
+ ])));
1185
911
  }
1186
- function modifyPaginationButtons(blockStatement, detectedPaginations, paginationInfos) {
1187
- var modifiedButtons = new Set();
1188
- var modifyNode = function (node) {
912
+ function wireSearchInput(inputNode, vars) {
913
+ // Remove existing onChange and value
914
+ 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); });
915
+ // Add onChange
916
+ inputNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onChange'), types.jsxExpressionContainer(types.arrowFunctionExpression([types.identifier('e')], types.callExpression(types.identifier(vars.setSearchQueryVar), [
917
+ types.memberExpression(types.memberExpression(types.identifier('e'), types.identifier('target')), types.identifier('value')),
918
+ ])))));
919
+ // Add value
920
+ inputNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('value'), types.jsxExpressionContainer(types.identifier(vars.searchQueryVar))));
921
+ }
922
+ function wirePaginationButtons(paginationNode, usage, vars) {
923
+ // Find prev and next buttons
924
+ var findButton = function (node, direction) {
925
+ var _a, _b, _c, _d, _e;
1189
926
  if (!node) {
1190
- return;
927
+ return null;
1191
928
  }
1192
929
  if (node.type === 'JSXElement') {
1193
- var openingElement = node.openingElement;
1194
- if (openingElement && openingElement.name && openingElement.name.type === 'JSXIdentifier') {
1195
- var className = getClassName(openingElement.attributes);
1196
- if (className && !modifiedButtons.has(node)) {
1197
- for (var index = 0; index < detectedPaginations.length; index++) {
1198
- var detected = detectedPaginations[index];
1199
- var info = paginationInfos[index];
1200
- if (!info) {
1201
- continue;
1202
- }
1203
- if (className === detected.prevButtonClass) {
1204
- convertToButton(node, info, 'prev');
1205
- modifiedButtons.add(node);
1206
- break;
1207
- }
1208
- else if (className === detected.nextButtonClass) {
1209
- convertToButton(node, info, 'next');
1210
- modifiedButtons.add(node);
1211
- break;
1212
- }
1213
- }
1214
- }
930
+ var classAttr = (_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.attributes) === null || _b === void 0 ? void 0 : _b.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'className'; });
931
+ var className = ((_c = classAttr === null || classAttr === void 0 ? void 0 : classAttr.value) === null || _c === void 0 ? void 0 : _c.value) || ((_e = (_d = classAttr === null || classAttr === void 0 ? void 0 : classAttr.value) === null || _d === void 0 ? void 0 : _d.expression) === null || _e === void 0 ? void 0 : _e.value) || '';
932
+ if (className.includes(direction)) {
933
+ return node;
1215
934
  }
1216
935
  }
1217
- if (typeof node === 'object') {
1218
- Object.values(node).forEach(function (value) {
1219
- if (Array.isArray(value)) {
1220
- value.forEach(function (item) { return modifyNode(item); });
1221
- }
1222
- else if (typeof value === 'object') {
1223
- modifyNode(value);
936
+ if (node.children && Array.isArray(node.children)) {
937
+ for (var _i = 0, _f = node.children; _i < _f.length; _i++) {
938
+ var c = _f[_i];
939
+ var found = findButton(c, direction);
940
+ if (found) {
941
+ return found;
1224
942
  }
1225
- });
943
+ }
1226
944
  }
945
+ return null;
1227
946
  };
1228
- modifyNode(blockStatement);
1229
- }
1230
- function modifySearchInputs(blockStatement, detectedPaginations, paginationInfos) {
1231
- var modifiedInputs = new Set();
1232
- var modifyNode = function (node) {
1233
- if (!node) {
1234
- return;
947
+ var prevButton = findButton(paginationNode, 'previous');
948
+ var nextButton = findButton(paginationNode, 'next');
949
+ var isCombinedState = usage.category === 'paginated+search';
950
+ if (prevButton) {
951
+ // Change to button element
952
+ prevButton.openingElement.name.name = 'button';
953
+ if (prevButton.closingElement) {
954
+ prevButton.closingElement.name.name = 'button';
1235
955
  }
1236
- if (node.type === 'JSXElement') {
1237
- var openingElement = node.openingElement;
1238
- if (openingElement && openingElement.name && openingElement.name.type === 'JSXIdentifier') {
1239
- var className = getClassName(openingElement.attributes);
1240
- if (className && !modifiedInputs.has(node)) {
1241
- for (var index = 0; index < detectedPaginations.length; index++) {
1242
- var detected = detectedPaginations[index];
1243
- var info = paginationInfos[index];
1244
- if (!info || !info.searchEnabled) {
1245
- continue;
1246
- }
1247
- if (className === detected.searchInputClass) {
1248
- addSearchInputHandlers(node, info);
1249
- modifiedInputs.add(node);
1250
- break;
1251
- }
1252
- }
1253
- }
1254
- }
1255
- }
1256
- if (typeof node === 'object') {
1257
- Object.values(node).forEach(function (value) {
1258
- if (Array.isArray(value)) {
1259
- value.forEach(function (item) { return modifyNode(item); });
1260
- }
1261
- else if (typeof value === 'object') {
1262
- modifyNode(value);
1263
- }
1264
- });
956
+ // Add type="button"
957
+ var hasType = prevButton.openingElement.attributes.some(function (a) { var _a; return ((_a = a.name) === null || _a === void 0 ? void 0 : _a.name) === 'type'; });
958
+ if (!hasType) {
959
+ prevButton.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('type'), types.stringLiteral('button')));
1265
960
  }
1266
- };
1267
- modifyNode(blockStatement);
1268
- }
1269
- function addSearchInputHandlers(jsxElement, info) {
1270
- if (!info.searchQueryVar || !info.setSearchQueryVar) {
1271
- return;
1272
- }
1273
- var openingElement = jsxElement.openingElement;
1274
- removeAttribute(openingElement.attributes, 'onChange');
1275
- removeAttribute(openingElement.attributes, 'value');
1276
- var onChangeHandler = types.arrowFunctionExpression([types.identifier('e')], types.callExpression(types.identifier(info.setSearchQueryVar), [
1277
- types.memberExpression(types.memberExpression(types.identifier('e'), types.identifier('target')), types.identifier('value')),
1278
- ]));
1279
- openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onChange'), types.jsxExpressionContainer(onChangeHandler)));
1280
- openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('value'), types.jsxExpressionContainer(types.identifier(info.searchQueryVar))));
1281
- }
1282
- function convertToButton(jsxElement, info, buttonType) {
1283
- var openingElement = jsxElement.openingElement;
1284
- if (openingElement.name.type === 'JSXIdentifier') {
1285
- openingElement.name.name = 'button';
1286
- }
1287
- if (jsxElement.closingElement && jsxElement.closingElement.name.type === 'JSXIdentifier') {
1288
- jsxElement.closingElement.name.name = 'button';
1289
- }
1290
- removeAttribute(openingElement.attributes, 'onClick');
1291
- removeAttribute(openingElement.attributes, 'disabled');
1292
- removeAttribute(openingElement.attributes, 'type');
1293
- var combinedStateVar = info.combinedStateVar;
1294
- var setCombinedStateVar = info.setCombinedStateVar;
1295
- var onClickHandler;
1296
- if (info.searchEnabled && combinedStateVar && setCombinedStateVar) {
1297
- // Use combined state: update only the page property
1298
- onClickHandler =
1299
- buttonType === 'prev'
1300
- ? types.arrowFunctionExpression([], types.callExpression(types.identifier(setCombinedStateVar), [
1301
- types.arrowFunctionExpression([types.identifier('state')], types.objectExpression([
1302
- types.spreadElement(types.identifier('state')),
1303
- types.objectProperty(types.identifier('page'), types.callExpression(types.memberExpression(types.identifier('Math'), types.identifier('max')), [
1304
- types.numericLiteral(1),
1305
- types.binaryExpression('-', types.memberExpression(types.identifier('state'), types.identifier('page')), types.numericLiteral(1)),
1306
- ])),
1307
- ])),
1308
- ]))
1309
- : types.arrowFunctionExpression([], types.callExpression(types.identifier(setCombinedStateVar), [
1310
- types.arrowFunctionExpression([types.identifier('state')], types.objectExpression([
1311
- types.spreadElement(types.identifier('state')),
1312
- types.objectProperty(types.identifier('page'), types.binaryExpression('+', types.memberExpression(types.identifier('state'), types.identifier('page')), types.numericLiteral(1))),
1313
- ])),
1314
- ]));
1315
- }
1316
- else {
1317
- // Regular pagination (no search)
1318
- onClickHandler =
1319
- buttonType === 'prev'
1320
- ? types.arrowFunctionExpression([], types.callExpression(types.identifier(info.setPageStateVar), [
1321
- types.arrowFunctionExpression([types.identifier('p')], types.callExpression(types.memberExpression(types.identifier('Math'), types.identifier('max')), [
961
+ // Add onClick
962
+ prevButton.openingElement.attributes = prevButton.openingElement.attributes.filter(function (a) { var _a; return ((_a = a.name) === null || _a === void 0 ? void 0 : _a.name) !== 'onClick'; });
963
+ if (isCombinedState) {
964
+ prevButton.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onClick'), types.jsxExpressionContainer(types.arrowFunctionExpression([], types.callExpression(types.identifier(vars.setCombinedStateVar), [
965
+ types.arrowFunctionExpression([types.identifier('state')], types.objectExpression([
966
+ types.spreadElement(types.identifier('state')),
967
+ types.objectProperty(types.identifier('page'), types.callExpression(types.memberExpression(types.identifier('Math'), types.identifier('max')), [
1322
968
  types.numericLiteral(1),
1323
- types.binaryExpression('-', types.identifier('p'), types.numericLiteral(1)),
969
+ types.binaryExpression('-', types.memberExpression(types.identifier('state'), types.identifier('page')), types.numericLiteral(1)),
1324
970
  ])),
1325
- ]))
1326
- : types.arrowFunctionExpression([], types.callExpression(types.identifier(info.setPageStateVar), [
1327
- types.arrowFunctionExpression([types.identifier('p')], types.binaryExpression('+', types.identifier('p'), types.numericLiteral(1))),
1328
- ]));
1329
- }
1330
- openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onClick'), types.jsxExpressionContainer(onClickHandler)));
1331
- openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('type'), types.stringLiteral('button')));
1332
- // Add disabled attribute with simple page number checks
1333
- var maxPagesStateVar = info.maxPagesStateVar;
1334
- var disabledExpr;
1335
- if (info.searchEnabled && combinedStateVar) {
1336
- disabledExpr =
1337
- buttonType === 'prev'
1338
- ? types.binaryExpression('<=', types.memberExpression(types.identifier(combinedStateVar), types.identifier('page')), types.numericLiteral(1))
1339
- : types.binaryExpression('>=', types.memberExpression(types.identifier(combinedStateVar), types.identifier('page')), types.identifier(maxPagesStateVar));
1340
- }
1341
- else {
1342
- disabledExpr =
1343
- buttonType === 'prev'
1344
- ? types.binaryExpression('<=', types.identifier(info.pageStateVar), types.numericLiteral(1))
1345
- : types.binaryExpression('>=', types.identifier(info.pageStateVar), types.identifier(maxPagesStateVar));
971
+ ])),
972
+ ])))));
973
+ // Add disabled
974
+ prevButton.openingElement.attributes = prevButton.openingElement.attributes.filter(function (a) { var _a; return ((_a = a.name) === null || _a === void 0 ? void 0 : _a.name) !== 'disabled'; });
975
+ prevButton.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('disabled'), types.jsxExpressionContainer(types.binaryExpression('<=', types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('page')), types.numericLiteral(1)))));
976
+ }
977
+ else {
978
+ prevButton.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onClick'), types.jsxExpressionContainer(types.arrowFunctionExpression([], types.callExpression(types.identifier(vars.setPageStateVar), [
979
+ types.arrowFunctionExpression([types.identifier('page')], types.callExpression(types.memberExpression(types.identifier('Math'), types.identifier('max')), [
980
+ types.numericLiteral(1),
981
+ types.binaryExpression('-', types.identifier('page'), types.numericLiteral(1)),
982
+ ])),
983
+ ])))));
984
+ prevButton.openingElement.attributes = prevButton.openingElement.attributes.filter(function (a) { var _a; return ((_a = a.name) === null || _a === void 0 ? void 0 : _a.name) !== 'disabled'; });
985
+ prevButton.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('disabled'), types.jsxExpressionContainer(types.binaryExpression('<=', types.identifier(vars.pageStateVar), types.numericLiteral(1)))));
986
+ }
1346
987
  }
1347
- openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('disabled'), types.jsxExpressionContainer(disabledExpr)));
1348
- }
1349
- function getClassName(attributes) {
1350
- var classNameAttr = attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'className'; });
1351
- if (classNameAttr && classNameAttr.value && classNameAttr.value.type === 'StringLiteral') {
1352
- return classNameAttr.value.value;
988
+ if (nextButton) {
989
+ nextButton.openingElement.name.name = 'button';
990
+ if (nextButton.closingElement) {
991
+ nextButton.closingElement.name.name = 'button';
992
+ }
993
+ var hasType = nextButton.openingElement.attributes.some(function (a) { var _a; return ((_a = a.name) === null || _a === void 0 ? void 0 : _a.name) === 'type'; });
994
+ if (!hasType) {
995
+ nextButton.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('type'), types.stringLiteral('button')));
996
+ }
997
+ nextButton.openingElement.attributes = nextButton.openingElement.attributes.filter(function (a) { var _a; return ((_a = a.name) === null || _a === void 0 ? void 0 : _a.name) !== 'onClick'; });
998
+ if (isCombinedState) {
999
+ nextButton.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onClick'), types.jsxExpressionContainer(types.arrowFunctionExpression([], types.callExpression(types.identifier(vars.setCombinedStateVar), [
1000
+ types.arrowFunctionExpression([types.identifier('state')], types.objectExpression([
1001
+ types.spreadElement(types.identifier('state')),
1002
+ types.objectProperty(types.identifier('page'), types.binaryExpression('+', types.memberExpression(types.identifier('state'), types.identifier('page')), types.numericLiteral(1))),
1003
+ ])),
1004
+ ])))));
1005
+ nextButton.openingElement.attributes = nextButton.openingElement.attributes.filter(function (a) { var _a; return ((_a = a.name) === null || _a === void 0 ? void 0 : _a.name) !== 'disabled'; });
1006
+ nextButton.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('disabled'), types.jsxExpressionContainer(types.binaryExpression('>=', types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('page')), types.identifier(vars.maxPagesStateVar)))));
1007
+ }
1008
+ else {
1009
+ nextButton.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onClick'), types.jsxExpressionContainer(types.arrowFunctionExpression([], types.callExpression(types.identifier(vars.setPageStateVar), [
1010
+ types.arrowFunctionExpression([types.identifier('page')], types.binaryExpression('+', types.identifier('page'), types.numericLiteral(1))),
1011
+ ])))));
1012
+ nextButton.openingElement.attributes = nextButton.openingElement.attributes.filter(function (a) { var _a; return ((_a = a.name) === null || _a === void 0 ? void 0 : _a.name) !== 'disabled'; });
1013
+ nextButton.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('disabled'), types.jsxExpressionContainer(types.binaryExpression('>=', types.identifier(vars.pageStateVar), types.identifier(vars.maxPagesStateVar)))));
1014
+ }
1353
1015
  }
1354
- return null;
1355
1016
  }
1356
- function removeAttribute(attrs, attributeName) {
1357
- var index = attrs.findIndex(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === attributeName; });
1358
- if (index !== -1) {
1359
- attrs.splice(index, 1);
1017
+ function ensureAPIRouteExists(extractedResources, usage) {
1018
+ // Generate file name for the API route
1019
+ var fileName = (0, utils_1.generateSafeFileName)(usage.resourceDefinition.dataSourceType, usage.resourceDefinition.tableName, usage.resourceDefinition.dataSourceId);
1020
+ // Check if the utils data source file exists - if so, create API routes that re-export from it
1021
+ if (extractedResources["utils/".concat(fileName)]) {
1022
+ // Create main data API route if not exists
1023
+ if (!extractedResources["api/".concat(fileName)]) {
1024
+ var apiRouteCode = "import dataSourceModule from '../../utils/data-sources/".concat(fileName, "'\n\nexport default dataSourceModule.handler\n");
1025
+ extractedResources["api/".concat(fileName)] = {
1026
+ fileName: fileName,
1027
+ fileType: teleport_types_1.FileType.JS,
1028
+ path: ['pages', 'api'],
1029
+ content: apiRouteCode,
1030
+ };
1031
+ }
1032
+ // Create count API route if not exists (needed for paginated+search cases)
1033
+ var countFileName = "".concat(fileName, "-count");
1034
+ if (!extractedResources["api/".concat(countFileName)]) {
1035
+ var countApiRouteCode = "import dataSourceModule from '../../utils/data-sources/".concat(fileName, "'\n\nexport default dataSourceModule.getCount\n");
1036
+ extractedResources["api/".concat(countFileName)] = {
1037
+ fileName: countFileName,
1038
+ fileType: teleport_types_1.FileType.JS,
1039
+ path: ['pages', 'api'],
1040
+ content: countApiRouteCode,
1041
+ };
1042
+ }
1360
1043
  }
1361
1044
  }
1362
- function modifyGetStaticPropsForPagination(chunks, paginationInfos) {
1045
+ function updateGetStaticProps(chunks, registry) {
1363
1046
  var _a;
1364
- var getStaticPropsChunk = chunks.find(function (chunk) { return chunk.name === 'getStaticProps'; });
1365
- if (!getStaticPropsChunk || getStaticPropsChunk.type !== 'ast') {
1047
+ var getStaticPropsChunk = chunks.find(function (c) { return c.name === 'getStaticProps'; });
1048
+ if (!getStaticPropsChunk || getStaticPropsChunk.type !== teleport_types_1.ChunkType.AST) {
1366
1049
  return;
1367
1050
  }
1368
- var exportDeclaration = getStaticPropsChunk.content;
1369
- if (!exportDeclaration || exportDeclaration.type !== 'ExportNamedDeclaration') {
1051
+ var content = getStaticPropsChunk.content;
1052
+ if (!content.declaration || content.declaration.type !== 'FunctionDeclaration') {
1370
1053
  return;
1371
1054
  }
1372
- var functionDeclaration = exportDeclaration.declaration;
1373
- if (!functionDeclaration || functionDeclaration.type !== 'FunctionDeclaration') {
1055
+ var funcBody = content.declaration.body;
1056
+ var tryStmt = funcBody.body.find(function (s) { return s.type === 'TryStatement'; });
1057
+ if (!tryStmt) {
1374
1058
  return;
1375
1059
  }
1376
- // Find Promise.all and add NEW fetchData calls for each paginated DataProvider
1377
- var functionBody = functionDeclaration.body.body;
1378
- var tryBlock = functionBody.find(function (stmt) { return stmt.type === 'TryStatement'; });
1379
- if (!tryBlock) {
1380
- return;
1381
- }
1382
- var tryBody = tryBlock.block.body;
1383
- // Find the Promise.all statement
1384
- var promiseAllStmt = tryBody.find(function (stmt) {
1060
+ var tryBlock = tryStmt.block;
1061
+ // Find existing Promise.all
1062
+ var promiseAllDecl = tryBlock.body.find(function (s) {
1385
1063
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
1386
- return stmt.type === 'VariableDeclaration' &&
1387
- ((_c = (_b = (_a = stmt.declarations) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.init) === null || _c === void 0 ? void 0 : _c.type) === 'AwaitExpression' &&
1388
- ((_g = (_f = (_e = (_d = stmt.declarations) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.init) === null || _f === void 0 ? void 0 : _f.argument) === null || _g === void 0 ? void 0 : _g.type) === 'CallExpression' &&
1389
- ((_m = (_l = (_k = (_j = (_h = stmt.declarations) === null || _h === void 0 ? void 0 : _h[0]) === null || _j === void 0 ? void 0 : _j.init) === null || _k === void 0 ? void 0 : _k.argument) === null || _l === void 0 ? void 0 : _l.callee) === null || _m === void 0 ? void 0 : _m.type) === 'MemberExpression' &&
1390
- ((_t = (_s = (_r = (_q = (_p = (_o = stmt.declarations) === null || _o === void 0 ? void 0 : _o[0]) === null || _p === void 0 ? void 0 : _p.init) === null || _q === void 0 ? void 0 : _q.argument) === null || _r === void 0 ? void 0 : _r.callee) === null || _s === void 0 ? void 0 : _s.property) === null || _t === void 0 ? void 0 : _t.name) === 'all';
1064
+ return s.type === 'VariableDeclaration' &&
1065
+ ((_c = (_b = (_a = s.declarations) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.init) === null || _c === void 0 ? void 0 : _c.type) === 'AwaitExpression' &&
1066
+ ((_g = (_f = (_e = (_d = s.declarations) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.init) === null || _f === void 0 ? void 0 : _f.argument) === null || _g === void 0 ? void 0 : _g.type) === 'CallExpression' &&
1067
+ ((_m = (_l = (_k = (_j = (_h = s.declarations) === null || _h === void 0 ? void 0 : _h[0]) === null || _j === void 0 ? void 0 : _j.init) === null || _k === void 0 ? void 0 : _k.argument) === null || _l === void 0 ? void 0 : _l.callee) === null || _m === void 0 ? void 0 : _m.type) === 'MemberExpression' &&
1068
+ ((_t = (_s = (_r = (_q = (_p = (_o = s.declarations) === null || _o === void 0 ? void 0 : _o[0]) === null || _p === void 0 ? void 0 : _p.init) === null || _q === void 0 ? void 0 : _q.argument) === null || _r === void 0 ? void 0 : _r.callee) === null || _s === void 0 ? void 0 : _s.object) === null || _t === void 0 ? void 0 : _t.name) === 'Promise';
1391
1069
  });
1392
- if (!promiseAllStmt) {
1070
+ if (!promiseAllDecl) {
1393
1071
  return;
1394
1072
  }
1395
- var awaitExpr = promiseAllStmt.declarations[0].init;
1073
+ var declarator = promiseAllDecl.declarations[0];
1074
+ var awaitExpr = declarator.init;
1396
1075
  var promiseAllCall = awaitExpr.argument;
1397
- var promiseArray = promiseAllCall.arguments[0];
1398
- var destructuringPattern = promiseAllStmt.declarations[0].id;
1399
- // Map import names to data source identifiers from existing fetchData calls
1400
- // Also track which indices to remove (non-paginated calls that will be replaced)
1401
- var importToDataSource = new Map();
1402
- var indicesToRemove = [];
1403
- promiseArray.elements.forEach(function (element, index) {
1404
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
1405
- if (element && element.type === 'CallExpression') {
1406
- var fetchCallExpr = element;
1407
- // If wrapped in .catch(), unwrap it
1408
- if (((_a = element.callee) === null || _a === void 0 ? void 0 : _a.type) === 'MemberExpression' &&
1409
- ((_c = (_b = element.callee) === null || _b === void 0 ? void 0 : _b.property) === null || _c === void 0 ? void 0 : _c.name) === 'catch' &&
1410
- ((_e = (_d = element.callee) === null || _d === void 0 ? void 0 : _d.object) === null || _e === void 0 ? void 0 : _e.type) === 'CallExpression') {
1411
- fetchCallExpr = element.callee.object;
1412
- }
1413
- // Now find the .fetchData() call
1414
- if (((_f = fetchCallExpr.callee) === null || _f === void 0 ? void 0 : _f.type) === 'MemberExpression' &&
1415
- ((_h = (_g = fetchCallExpr.callee) === null || _g === void 0 ? void 0 : _g.property) === null || _h === void 0 ? void 0 : _h.name) === 'fetchData' &&
1416
- ((_k = (_j = fetchCallExpr.callee) === null || _j === void 0 ? void 0 : _j.object) === null || _k === void 0 ? void 0 : _k.type) === 'Identifier') {
1417
- var importName = fetchCallExpr.callee.object.name;
1418
- var dataSourceVar_1 = destructuringPattern.elements[index].name;
1419
- // Check if this fetchData call has page/perPage params
1420
- var params = fetchCallExpr.arguments[0];
1421
- var hasPageParam = params &&
1422
- params.type === 'ObjectExpression' &&
1423
- params.properties.some(function (prop) {
1424
- return prop.type === 'ObjectProperty' &&
1425
- (prop.key.name === 'page' || prop.key.name === 'perPage');
1426
- });
1427
- // If this is a data source that will be paginated but this call has NO pagination params,
1428
- // mark it for removal
1429
- if (!hasPageParam &&
1430
- paginationInfos.some(function (info) { return info.dataSourceIdentifier === dataSourceVar_1; })) {
1431
- indicesToRemove.push(index);
1432
- }
1433
- importToDataSource.set(importName, dataSourceVar_1);
1434
- }
1076
+ var fetchesArray = promiseAllCall.arguments[0];
1077
+ // Find return statement
1078
+ var returnStmt = tryBlock.body.find(function (s) { return s.type === 'ReturnStatement'; });
1079
+ if (!returnStmt || ((_a = returnStmt.argument) === null || _a === void 0 ? void 0 : _a.type) !== 'ObjectExpression') {
1080
+ return;
1081
+ }
1082
+ var returnObj = returnStmt.argument;
1083
+ var propsProperty = returnObj.properties.find(function (p) { return p.type === 'ObjectProperty' && p.key.type === 'Identifier' && p.key.name === 'props'; });
1084
+ if (!propsProperty || propsProperty.value.type !== 'ObjectExpression') {
1085
+ return;
1086
+ }
1087
+ var propsObj = propsProperty.value;
1088
+ var arrayPattern = declarator.id;
1089
+ // Track unique data sources for count fetching
1090
+ var dataSourcesNeedingCount = new Set();
1091
+ registry.usages.forEach(function (usage) {
1092
+ var vars = getStateVarsForUsage(usage);
1093
+ var fileName = (0, utils_1.generateSafeFileName)(usage.resourceDefinition.dataSourceType, usage.resourceDefinition.tableName, usage.resourceDefinition.dataSourceId);
1094
+ // Use consistent import name generation (matches extractDataSourceIntoGetStaticProps)
1095
+ var fetcherImportName = teleport_shared_1.StringUtils.dashCaseToCamelCase(fileName);
1096
+ // Add fetch call
1097
+ var fetchParams = [];
1098
+ if (usage.paginated) {
1099
+ // For paginated array mappers, add page and perPage
1100
+ fetchParams.push(types.objectProperty(types.identifier('page'), types.numericLiteral(1)));
1101
+ fetchParams.push(types.objectProperty(types.identifier('perPage'), types.numericLiteral(usage.perPage)));
1435
1102
  }
1436
- });
1437
- // Remove non-paginated fetchData calls in reverse order to preserve indices
1438
- indicesToRemove.reverse().forEach(function (index) {
1439
- var _a, _b;
1440
- // Get the prop name BEFORE removing it
1441
- var propToRemove = (_a = destructuringPattern.elements[index]) === null || _a === void 0 ? void 0 : _a.name;
1442
- promiseArray.elements.splice(index, 1);
1443
- destructuringPattern.elements.splice(index, 1);
1444
- // Also remove from props in return statement
1445
- if (propToRemove) {
1446
- var foundReturnStmt = tryBody.find(function (stmt) { return stmt.type === 'ReturnStatement'; });
1447
- if (foundReturnStmt && ((_b = foundReturnStmt.argument) === null || _b === void 0 ? void 0 : _b.type) === 'ObjectExpression') {
1448
- var propsProperty = foundReturnStmt.argument.properties.find(function (prop) {
1449
- return prop.type === 'ObjectProperty' && prop.key.name === 'props';
1450
- });
1451
- if (propsProperty && propsProperty.value.type === 'ObjectExpression') {
1452
- var propsObject = propsProperty.value;
1453
- var propIndex = propsObject.properties.findIndex(function (prop) {
1454
- return prop.type === 'ObjectProperty' && prop.key.name === propToRemove;
1455
- });
1456
- if (propIndex !== -1) {
1457
- propsObject.properties.splice(propIndex, 1);
1458
- }
1459
- }
1460
- }
1103
+ else if (usage.perPage > 0) {
1104
+ // For non-paginated array mappers with a limit, add the limit as perPage
1105
+ // This ensures the initial data fetch respects the limit from the UIDL
1106
+ fetchParams.push(types.objectProperty(types.identifier('perPage'), types.numericLiteral(usage.perPage)));
1461
1107
  }
1462
- });
1463
- // Add NEW fetchData calls for each paginated DataProvider
1464
- paginationInfos.forEach(function (info, index) {
1465
- var _a, _b;
1466
- // Try exact match first, then case-insensitive match
1467
- var importName = (_a = Array.from(importToDataSource.entries()).find(function (_a) {
1468
- var _ = _a[0], dataSourceVar = _a[1];
1469
- return dataSourceVar === info.dataSourceIdentifier;
1470
- })) === null || _a === void 0 ? void 0 : _a[0];
1471
- if (!importName) {
1472
- // Try case-insensitive match
1473
- var normalizedIdentifier_1 = info.dataSourceIdentifier.toLowerCase().replace(/[_-]/g, '');
1474
- importName = (_b = Array.from(importToDataSource.entries()).find(function (_a) {
1475
- var _ = _a[0], dataSourceVar = _a[1];
1476
- return dataSourceVar.toLowerCase().replace(/[_-]/g, '') === normalizedIdentifier_1;
1477
- })) === null || _b === void 0 ? void 0 : _b[0];
1108
+ if (usage.queryColumns.length > 0) {
1109
+ fetchParams.push(types.objectProperty(types.identifier('queryColumns'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [types.arrayExpression(usage.queryColumns.map(function (c) { return types.stringLiteral(c); }))])));
1478
1110
  }
1479
- if (importName) {
1480
- var paginatedVarName = "".concat(info.dataSourceIdentifier, "_pg_").concat(index);
1481
- var fetchParams = [
1482
- types.objectProperty(types.identifier('page'), types.numericLiteral(1)),
1483
- types.objectProperty(types.identifier('perPage'), types.numericLiteral(info.perPage)),
1484
- ];
1485
- // Add queryColumns if they exist
1486
- if (info.queryColumns && info.queryColumns.length > 0) {
1487
- fetchParams.push(types.objectProperty(types.identifier('queryColumns'), types.arrayExpression(info.queryColumns.map(function (col) { return types.stringLiteral(col); }))));
1488
- }
1489
- // Create new fetchData call with pagination params
1490
- var newFetchDataCall = types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.identifier(importName), types.identifier('fetchData')), [types.objectExpression(fetchParams)]), types.identifier('catch')), [
1111
+ // Check if this fetch already exists
1112
+ var existingFetchIndex = arrayPattern.elements.findIndex(function (el) { return (el === null || el === void 0 ? void 0 : el.type) === 'Identifier' && el.name === vars.propsPrefix; });
1113
+ if (existingFetchIndex === -1) {
1114
+ arrayPattern.elements.push(types.identifier(vars.propsPrefix));
1115
+ fetchesArray.elements.push(types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.identifier(fetcherImportName), types.identifier('fetchData')), [types.objectExpression(fetchParams)]), types.identifier('catch')), [
1491
1116
  types.arrowFunctionExpression([types.identifier('error')], types.blockStatement([
1492
1117
  types.expressionStatement(types.callExpression(types.memberExpression(types.identifier('console'), types.identifier('error')), [
1493
- types.stringLiteral("Error fetching ".concat(paginatedVarName, ":")),
1118
+ types.stringLiteral("Error fetching ".concat(vars.propsPrefix, ":")),
1494
1119
  types.identifier('error'),
1495
1120
  ])),
1496
1121
  types.returnStatement(types.arrayExpression([])),
1497
1122
  ])),
1498
- ]);
1499
- promiseArray.elements.push(newFetchDataCall);
1500
- destructuringPattern.elements.push(types.identifier(paginatedVarName));
1123
+ ]));
1124
+ // Add to props
1125
+ propsObj.properties.push(types.objectProperty(types.identifier(vars.propsPrefix), types.identifier(vars.propsPrefix)));
1501
1126
  }
1502
- });
1503
- // Add fetchCount calls for paginated data sources (deduplicated by data source)
1504
- // Deduplicate by data source identifier
1505
- var uniqueDataSources = new Set(paginationInfos.map(function (info) { return info.dataSourceIdentifier; }));
1506
- var addedCountFetches = new Set();
1507
- uniqueDataSources.forEach(function (dataSourceId) {
1508
- var _a, _b;
1509
- var importName = (_a = Array.from(importToDataSource.entries()).find(function (_a) {
1510
- var _ = _a[0], dataSourceVar = _a[1];
1511
- return dataSourceVar === dataSourceId;
1512
- })) === null || _a === void 0 ? void 0 : _a[0];
1513
- if (!importName) {
1514
- // Try case-insensitive match
1515
- var normalizedIdentifier_2 = dataSourceId.toLowerCase().replace(/[_-]/g, '');
1516
- importName = (_b = Array.from(importToDataSource.entries()).find(function (_a) {
1517
- var _ = _a[0], dataSourceVar = _a[1];
1518
- return dataSourceVar.toLowerCase().replace(/[_-]/g, '') === normalizedIdentifier_2;
1519
- })) === null || _b === void 0 ? void 0 : _b[0];
1127
+ // Track for count fetching
1128
+ if (usage.paginated) {
1129
+ dataSourcesNeedingCount.add("".concat(usage.resourceDefinition.dataSourceType, ":").concat(usage.resourceDefinition.tableName, ":").concat(usage.resourceDefinition.dataSourceId));
1520
1130
  }
1521
- if (importName && !addedCountFetches.has(dataSourceId)) {
1522
- var fetchCountCall = types.callExpression(types.memberExpression(types.identifier(importName), types.identifier('fetchCount')), []);
1523
- promiseArray.elements.push(fetchCountCall);
1524
- destructuringPattern.elements.push(types.identifier("".concat(dataSourceId, "_count")));
1525
- addedCountFetches.add(dataSourceId);
1526
- }
1527
- });
1528
- // Calculate and add maxPages before return
1529
- var returnStmt = tryBody.find(function (stmt) { return stmt.type === 'ReturnStatement'; });
1530
- if (returnStmt && ((_a = returnStmt.argument) === null || _a === void 0 ? void 0 : _a.type) === 'ObjectExpression') {
1531
- var propsProperty = returnStmt.argument.properties.find(function (prop) {
1532
- return prop.type === 'ObjectProperty' && prop.key.name === 'props';
1533
- });
1534
- if (propsProperty && propsProperty.value.type === 'ObjectExpression') {
1535
- var propsObject_1 = propsProperty.value;
1536
- var returnIndex_1 = tryBody.indexOf(returnStmt);
1537
- paginationInfos.forEach(function (info, index) {
1538
- var paginatedVarName = "".concat(info.dataSourceIdentifier, "_pg_").concat(index);
1539
- var countVarName = "".concat(info.dataSourceIdentifier, "_count");
1540
- var maxPagesVarName = "".concat(info.dataSourceIdentifier, "_pg_").concat(index, "_maxPages");
1541
- var maxPagesCalc = types.variableDeclaration('const', [
1542
- types.variableDeclarator(types.identifier(maxPagesVarName), types.callExpression(types.memberExpression(types.identifier('Math'), types.identifier('ceil')), [
1543
- types.binaryExpression('/', types.logicalExpression('||', types.identifier(countVarName), types.numericLiteral(0)), types.numericLiteral(info.perPage)),
1131
+ // Add maxPages calculation for paginated
1132
+ if (usage.paginated) {
1133
+ var maxPagesPropName_1 = "".concat(vars.propsPrefix, "_maxPages");
1134
+ var countVarName = "".concat(usage.dataSourceIdentifier, "_count");
1135
+ // Check if maxPages calculation already exists
1136
+ var existingMaxPages = tryBlock.body.find(function (s) { var _a, _b, _c; return s.type === 'VariableDeclaration' && ((_c = (_b = (_a = s.declarations) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.id) === null || _c === void 0 ? void 0 : _c.name) === maxPagesPropName_1; });
1137
+ if (!existingMaxPages) {
1138
+ // Insert maxPages calculation before return
1139
+ var returnIndex = tryBlock.body.indexOf(returnStmt);
1140
+ tryBlock.body.splice(returnIndex, 0, types.variableDeclaration('const', [
1141
+ types.variableDeclarator(types.identifier(maxPagesPropName_1), types.callExpression(types.memberExpression(types.identifier('Math'), types.identifier('ceil')), [
1142
+ types.binaryExpression('/', types.logicalExpression('||', types.identifier(countVarName), types.numericLiteral(0)), types.numericLiteral(usage.perPage)),
1544
1143
  ])),
1545
- ]);
1546
- tryBody.splice(returnIndex_1, 0, maxPagesCalc);
1547
- // Add both the paginated data and maxPages to props
1548
- propsObject_1.properties.push(types.objectProperty(types.identifier(paginatedVarName), types.identifier(paginatedVarName)));
1549
- propsObject_1.properties.push(types.objectProperty(types.identifier(maxPagesVarName), types.identifier(maxPagesVarName)));
1550
- });
1551
- }
1552
- }
1553
- }
1554
- function createAPIRoutesForPaginatedDataSources(uidlNode, dataSources, componentChunk, extractedResources, paginationInfos, isComponent) {
1555
- var paginatedDataSourceIds = new Set(paginationInfos.map(function (info) { return info.dataSourceIdentifier; }));
1556
- var searchEnabledDataSources = new Set(paginationInfos.filter(function (info) { return info.searchEnabled; }).map(function (info) { return info.dataSourceIdentifier; }));
1557
- var createdCountRoutes = new Set();
1558
- var traverseForDataSources = function (node) {
1559
- var _a;
1560
- if (!node) {
1561
- return;
1562
- }
1563
- if (node.type === 'data-source-list' || node.type === 'data-source-item') {
1564
- var renderProp = node.content.renderPropIdentifier;
1565
- if (renderProp && paginatedDataSourceIds.has(renderProp)) {
1566
- (0, utils_1.extractDataSourceIntoNextAPIFolder)(node, dataSources, componentChunk, extractedResources);
1567
- var hasSearch = searchEnabledDataSources.has(renderProp);
1568
- var needsCountRoute = isComponent || hasSearch;
1569
- if (needsCountRoute) {
1570
- var resourceDef = node.content.resourceDefinition;
1571
- if (resourceDef) {
1572
- var dataSourceId = resourceDef.dataSourceId;
1573
- var tableName = resourceDef.tableName;
1574
- var dataSourceType = resourceDef.dataSourceType;
1575
- var fileName = "".concat(dataSourceType, "-").concat(tableName, "-").concat(dataSourceId.substring(0, 8));
1576
- var countFileName = "".concat(fileName, "-count");
1577
- if (!createdCountRoutes.has(countFileName)) {
1578
- extractedResources["api/".concat(countFileName)] = {
1579
- fileName: countFileName,
1580
- fileType: teleport_types_1.FileType.JS,
1581
- path: ['pages', 'api'],
1582
- content: "import dataSource from '../../utils/data-sources/".concat(fileName, "'\n\nexport default dataSource.getCount\n"),
1583
- };
1584
- createdCountRoutes.add(countFileName);
1585
- }
1586
- }
1587
- }
1144
+ ]));
1145
+ // Add maxPages to props
1146
+ propsObj.properties.push(types.objectProperty(types.identifier(maxPagesPropName_1), types.identifier(maxPagesPropName_1)));
1588
1147
  }
1589
1148
  }
1590
- if ((_a = node.content) === null || _a === void 0 ? void 0 : _a.children) {
1591
- node.content.children.forEach(function (child) { return traverseForDataSources(child); });
1592
- }
1593
- };
1594
- traverseForDataSources(uidlNode);
1595
- }
1596
- function createAPIRoutesForSearchOnlyDataSources(uidlNode, dataSources, componentChunk, extractedResources, searchOnlyDataSources) {
1597
- var searchOnlyDataSourceIds = new Set(searchOnlyDataSources.map(function (info) { return info.dataSourceIdentifier; }));
1598
- var traverseForDataSources = function (node) {
1599
- var _a;
1600
- if (!node) {
1149
+ });
1150
+ // Add count fetches for unique data sources
1151
+ dataSourcesNeedingCount.forEach(function (key) {
1152
+ var _a = key.split(':'), dataSourceType = _a[0], tableName = _a[1], dataSourceId = _a[2];
1153
+ var fileName = (0, utils_1.generateSafeFileName)(dataSourceType, tableName, dataSourceId);
1154
+ // Use consistent import name generation (matches extractDataSourceIntoGetStaticProps)
1155
+ var fetcherImportName = teleport_shared_1.StringUtils.dashCaseToCamelCase(fileName);
1156
+ // Find usage to get dataSourceIdentifier
1157
+ var usage = registry.usages.find(function (u) {
1158
+ return u.resourceDefinition.dataSourceId === dataSourceId &&
1159
+ u.resourceDefinition.tableName === tableName;
1160
+ });
1161
+ if (!usage) {
1601
1162
  return;
1602
1163
  }
1603
- if (node.type === 'data-source-list' || node.type === 'data-source-item') {
1604
- var renderProp = node.content.renderPropIdentifier;
1605
- if (renderProp && searchOnlyDataSourceIds.has(renderProp)) {
1606
- (0, utils_1.extractDataSourceIntoNextAPIFolder)(node, dataSources, componentChunk, extractedResources);
1607
- }
1608
- }
1609
- if ((_a = node.content) === null || _a === void 0 ? void 0 : _a.children) {
1610
- node.content.children.forEach(function (child) { return traverseForDataSources(child); });
1164
+ var countVarName = "".concat(usage.dataSourceIdentifier, "_count");
1165
+ // Check if count fetch already exists
1166
+ var existingCount = arrayPattern.elements.findIndex(function (el) { return (el === null || el === void 0 ? void 0 : el.type) === 'Identifier' && el.name === countVarName; });
1167
+ if (existingCount === -1) {
1168
+ arrayPattern.elements.push(types.identifier(countVarName));
1169
+ fetchesArray.elements.push(types.callExpression(types.memberExpression(types.identifier(fetcherImportName), types.identifier('fetchCount')), []));
1611
1170
  }
1612
- };
1613
- traverseForDataSources(uidlNode);
1171
+ });
1614
1172
  }
1615
- exports.default = (0, exports.createNextArrayMapperPaginationPlugin)();
1616
1173
  //# sourceMappingURL=pagination-plugin.js.map