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

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.
@@ -774,12 +774,95 @@ export const createNextArrayMapperPaginationPlugin: ComponentPluginFactory<{}> =
774
774
  )
775
775
  }
776
776
 
777
+ cleanupStaticDataProviders(blockStatement)
778
+
777
779
  return structure
778
780
  }
779
781
 
780
782
  return paginationPlugin
781
783
  }
782
784
 
785
+ function cleanupStaticDataProviders(blockStatement: types.BlockStatement): void {
786
+ const findAllDataProviders = (node: any, results: any[] = []): any[] => {
787
+ if (!node) {
788
+ return results
789
+ }
790
+
791
+ if (node.type === 'JSXElement' && node.openingElement?.name?.name === 'DataProvider') {
792
+ results.push(node)
793
+ }
794
+
795
+ if (node.type === 'ReturnStatement' && node.argument) {
796
+ findAllDataProviders(node.argument, results)
797
+ } else if (node.type === 'JSXElement' || node.type === 'JSXFragment') {
798
+ if (node.children && Array.isArray(node.children)) {
799
+ node.children.forEach((child: any) => findAllDataProviders(child, results))
800
+ }
801
+ } else if (node.type === 'JSXExpressionContainer') {
802
+ if (
803
+ node.expression &&
804
+ (node.expression.type === 'JSXElement' || node.expression.type === 'JSXFragment')
805
+ ) {
806
+ findAllDataProviders(node.expression, results)
807
+ }
808
+ } else if (node.type === 'BlockStatement') {
809
+ if (node.body && Array.isArray(node.body)) {
810
+ node.body.forEach((stmt: any) => findAllDataProviders(stmt, results))
811
+ }
812
+ } else if (node.type === 'ConditionalExpression') {
813
+ findAllDataProviders(node.consequent, results)
814
+ findAllDataProviders(node.alternate, results)
815
+ }
816
+
817
+ return results
818
+ }
819
+
820
+ const allDataProviders = findAllDataProviders(blockStatement)
821
+
822
+ allDataProviders.forEach((dataProvider) => {
823
+ const hasInitialData = dataProvider.openingElement.attributes.some(
824
+ (attr: any) => attr.type === 'JSXAttribute' && attr.name.name === 'initialData'
825
+ )
826
+ const hasFetchData = dataProvider.openingElement.attributes.some(
827
+ (attr: any) => attr.type === 'JSXAttribute' && attr.name.name === 'fetchData'
828
+ )
829
+ const paramsAttr = dataProvider.openingElement.attributes.find(
830
+ (attr: any) => attr.type === 'JSXAttribute' && attr.name.name === 'params'
831
+ )
832
+
833
+ // Case 1: Static SSR/SSG DataProviders (initialData, no fetchData, params)
834
+ // Remove params to prevent refetch attempts - data was already fetched in getStaticProps
835
+ if (hasInitialData && !hasFetchData && paramsAttr) {
836
+ dataProvider.openingElement.attributes = dataProvider.openingElement.attributes.filter(
837
+ (attr: any) => attr.type !== 'JSXAttribute' || attr.name.name !== 'params'
838
+ )
839
+ }
840
+
841
+ // Case 2: Client-side DataProviders with plain object params (fetchData, non-memoized params)
842
+ // Wrap params in useMemo to prevent infinite refetch loops
843
+ else if (hasFetchData && paramsAttr && paramsAttr.value?.type === 'JSXExpressionContainer') {
844
+ const paramsExpression = paramsAttr.value.expression
845
+
846
+ // Check if params are already memoized (useMemo or useCallback call)
847
+ const isAlreadyMemoized =
848
+ paramsExpression.type === 'CallExpression' &&
849
+ paramsExpression.callee.type === 'Identifier' &&
850
+ (paramsExpression.callee.name === 'useMemo' ||
851
+ paramsExpression.callee.name === 'useCallback')
852
+
853
+ // If params are a plain ObjectExpression, wrap in useMemo
854
+ if (!isAlreadyMemoized && paramsExpression.type === 'ObjectExpression') {
855
+ const memoizedParams = types.callExpression(types.identifier('useMemo'), [
856
+ types.arrowFunctionExpression([], paramsExpression),
857
+ types.arrayExpression([]), // Empty deps - params are static
858
+ ])
859
+
860
+ paramsAttr.value.expression = memoizedParams
861
+ }
862
+ }
863
+ })
864
+ }
865
+
783
866
  function findParentNode(root: any, target: any, currentParent: any = null): any | null {
784
867
  if (!root || !target) {
785
868
  return null
@@ -1049,14 +1132,16 @@ function detectPaginationsAndSearchFromJSX(
1049
1132
  } | null = null
1050
1133
  let searchInputInfo: { class: string | null; jsx: any } | null = null
1051
1134
 
1052
- const findSearchAndPaginationInScope = (scopeNode: any, skipNode: any = null): void => {
1135
+ const findSearchAndPaginationInScope = (scopeNode: any, skipNode: any = null): boolean => {
1053
1136
  if (!scopeNode || !scopeNode.children || !Array.isArray(scopeNode.children)) {
1054
- return
1137
+ return false
1055
1138
  }
1056
1139
 
1057
- scopeNode.children.forEach((child: any) => {
1140
+ let foundSomething = false
1141
+
1142
+ for (const child of scopeNode.children) {
1058
1143
  if (child === skipNode) {
1059
- return
1144
+ continue
1060
1145
  }
1061
1146
 
1062
1147
  if (child.type === 'JSXElement') {
@@ -1073,13 +1158,14 @@ function detectPaginationsAndSearchFromJSX(
1073
1158
  prevClass,
1074
1159
  nextClass,
1075
1160
  }
1161
+ foundSomething = true
1076
1162
  }
1077
1163
  }
1078
1164
 
1079
1165
  // Found search container - search for input inside it
1080
1166
  if (childClassName && childClassName.includes('data-source-search-node')) {
1081
1167
  if (child.children && Array.isArray(child.children)) {
1082
- child.children.forEach((searchChild: any) => {
1168
+ for (const searchChild of child.children) {
1083
1169
  if (searchChild.type === 'JSXElement') {
1084
1170
  const searchChildElementName = searchChild.openingElement?.name?.name
1085
1171
  const searchChildClassName = getClassName(
@@ -1094,9 +1180,10 @@ function detectPaginationsAndSearchFromJSX(
1094
1180
  class: searchChildClassName,
1095
1181
  jsx: searchChild,
1096
1182
  }
1183
+ foundSomething = true
1097
1184
  }
1098
1185
  }
1099
- })
1186
+ }
1100
1187
  }
1101
1188
  }
1102
1189
 
@@ -1110,13 +1197,24 @@ function detectPaginationsAndSearchFromJSX(
1110
1197
  class: childClassName,
1111
1198
  jsx: child,
1112
1199
  }
1200
+ foundSomething = true
1113
1201
  }
1114
1202
 
1203
+ // Stop searching if we found both or if we found what we're looking for
1204
+ if (foundSomething && (searchInputInfo || paginationNodeInfo)) {
1205
+ return true
1206
+ }
1207
+
1208
+ // Only recurse if we haven't found what we're looking for yet
1115
1209
  if (!searchInputInfo || !paginationNodeInfo) {
1116
- findSearchAndPaginationInScope(child, skipNode)
1210
+ if (findSearchAndPaginationInScope(child, skipNode)) {
1211
+ return true
1212
+ }
1117
1213
  }
1118
1214
  }
1119
- })
1215
+ }
1216
+
1217
+ return foundSomething
1120
1218
  }
1121
1219
 
1122
1220
  let currentScope = parent
@@ -1124,7 +1222,11 @@ function detectPaginationsAndSearchFromJSX(
1124
1222
  const maxDepth = 5
1125
1223
 
1126
1224
  while (currentScope && (!searchInputInfo || !paginationNodeInfo) && depth < maxDepth) {
1127
- findSearchAndPaginationInScope(currentScope, depth === 0 ? dataProvider : null)
1225
+ const found = findSearchAndPaginationInScope(currentScope, depth === 0 ? dataProvider : null)
1226
+ // Stop searching up the tree if we found a pagination node at this level
1227
+ if (found && paginationNodeInfo) {
1228
+ break
1229
+ }
1128
1230
  currentScope = findParentNode(blockStatement, currentScope)
1129
1231
  depth++
1130
1232
  }