@depup/base44__vite-plugin 1.0.4-depup.0

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 (167) hide show
  1. package/README.md +34 -0
  2. package/changes.json +22 -0
  3. package/compat/agents.cjs +13 -0
  4. package/compat/base44Client.cjs +6 -0
  5. package/compat/entities.cjs +25 -0
  6. package/compat/functions.cjs +9 -0
  7. package/compat/integrations.cjs +9 -0
  8. package/dist/ErrorOverlay.d.ts +12 -0
  9. package/dist/ErrorOverlay.d.ts.map +1 -0
  10. package/dist/ErrorOverlay.js +51 -0
  11. package/dist/ErrorOverlay.js.map +1 -0
  12. package/dist/bridge.d.ts +8 -0
  13. package/dist/bridge.d.ts.map +1 -0
  14. package/dist/bridge.js +8 -0
  15. package/dist/bridge.js.map +1 -0
  16. package/dist/capabilities/inline-edit/controller.d.ts +3 -0
  17. package/dist/capabilities/inline-edit/controller.d.ts.map +1 -0
  18. package/dist/capabilities/inline-edit/controller.js +203 -0
  19. package/dist/capabilities/inline-edit/controller.js.map +1 -0
  20. package/dist/capabilities/inline-edit/dom-utils.d.ts +7 -0
  21. package/dist/capabilities/inline-edit/dom-utils.d.ts.map +1 -0
  22. package/dist/capabilities/inline-edit/dom-utils.js +59 -0
  23. package/dist/capabilities/inline-edit/dom-utils.js.map +1 -0
  24. package/dist/capabilities/inline-edit/index.d.ts +3 -0
  25. package/dist/capabilities/inline-edit/index.d.ts.map +1 -0
  26. package/dist/capabilities/inline-edit/index.js +2 -0
  27. package/dist/capabilities/inline-edit/index.js.map +1 -0
  28. package/dist/capabilities/inline-edit/types.d.ts +29 -0
  29. package/dist/capabilities/inline-edit/types.d.ts.map +1 -0
  30. package/dist/capabilities/inline-edit/types.js +2 -0
  31. package/dist/capabilities/inline-edit/types.js.map +1 -0
  32. package/dist/consts.d.ts +11 -0
  33. package/dist/consts.d.ts.map +1 -0
  34. package/dist/consts.js +11 -0
  35. package/dist/consts.js.map +1 -0
  36. package/dist/error-overlay-plugin.d.ts +3 -0
  37. package/dist/error-overlay-plugin.d.ts.map +1 -0
  38. package/dist/error-overlay-plugin.js +15 -0
  39. package/dist/error-overlay-plugin.js.map +1 -0
  40. package/dist/html-injections-plugin.d.ts +8 -0
  41. package/dist/html-injections-plugin.d.ts.map +1 -0
  42. package/dist/html-injections-plugin.js +132 -0
  43. package/dist/html-injections-plugin.js.map +1 -0
  44. package/dist/index.d.ts +9 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +158 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/injections/layer-dropdown/consts.d.ts +20 -0
  49. package/dist/injections/layer-dropdown/consts.d.ts.map +1 -0
  50. package/dist/injections/layer-dropdown/consts.js +41 -0
  51. package/dist/injections/layer-dropdown/consts.js.map +1 -0
  52. package/dist/injections/layer-dropdown/controller.d.ts +4 -0
  53. package/dist/injections/layer-dropdown/controller.d.ts.map +1 -0
  54. package/dist/injections/layer-dropdown/controller.js +88 -0
  55. package/dist/injections/layer-dropdown/controller.js.map +1 -0
  56. package/dist/injections/layer-dropdown/dropdown-ui.d.ts +13 -0
  57. package/dist/injections/layer-dropdown/dropdown-ui.d.ts.map +1 -0
  58. package/dist/injections/layer-dropdown/dropdown-ui.js +186 -0
  59. package/dist/injections/layer-dropdown/dropdown-ui.js.map +1 -0
  60. package/dist/injections/layer-dropdown/types.d.ts +26 -0
  61. package/dist/injections/layer-dropdown/types.d.ts.map +1 -0
  62. package/dist/injections/layer-dropdown/types.js +3 -0
  63. package/dist/injections/layer-dropdown/types.js.map +1 -0
  64. package/dist/injections/layer-dropdown/utils.d.ts +25 -0
  65. package/dist/injections/layer-dropdown/utils.d.ts.map +1 -0
  66. package/dist/injections/layer-dropdown/utils.js +143 -0
  67. package/dist/injections/layer-dropdown/utils.js.map +1 -0
  68. package/dist/injections/navigation-notifier.d.ts +2 -0
  69. package/dist/injections/navigation-notifier.d.ts.map +1 -0
  70. package/dist/injections/navigation-notifier.js +34 -0
  71. package/dist/injections/navigation-notifier.js.map +1 -0
  72. package/dist/injections/sandbox-hmr-notifier.d.ts +2 -0
  73. package/dist/injections/sandbox-hmr-notifier.d.ts.map +1 -0
  74. package/dist/injections/sandbox-hmr-notifier.js +10 -0
  75. package/dist/injections/sandbox-hmr-notifier.js.map +1 -0
  76. package/dist/injections/sandbox-mount-observer.d.ts +2 -0
  77. package/dist/injections/sandbox-mount-observer.d.ts.map +1 -0
  78. package/dist/injections/sandbox-mount-observer.js +18 -0
  79. package/dist/injections/sandbox-mount-observer.js.map +1 -0
  80. package/dist/injections/unhandled-errors-handlers.d.ts +2 -0
  81. package/dist/injections/unhandled-errors-handlers.d.ts.map +1 -0
  82. package/dist/injections/unhandled-errors-handlers.js +93 -0
  83. package/dist/injections/unhandled-errors-handlers.js.map +1 -0
  84. package/dist/injections/utils.d.ts +65 -0
  85. package/dist/injections/utils.d.ts.map +1 -0
  86. package/dist/injections/utils.js +186 -0
  87. package/dist/injections/utils.js.map +1 -0
  88. package/dist/injections/visual-edit-agent.d.ts +2 -0
  89. package/dist/injections/visual-edit-agent.d.ts.map +1 -0
  90. package/dist/injections/visual-edit-agent.js +583 -0
  91. package/dist/injections/visual-edit-agent.js.map +1 -0
  92. package/dist/jsx-processor.d.ts +17 -0
  93. package/dist/jsx-processor.d.ts.map +1 -0
  94. package/dist/jsx-processor.js +129 -0
  95. package/dist/jsx-processor.js.map +1 -0
  96. package/dist/jsx-utils.d.ts +16 -0
  97. package/dist/jsx-utils.d.ts.map +1 -0
  98. package/dist/jsx-utils.js +98 -0
  99. package/dist/jsx-utils.js.map +1 -0
  100. package/dist/processors/collection-id-processor.d.ts +20 -0
  101. package/dist/processors/collection-id-processor.d.ts.map +1 -0
  102. package/dist/processors/collection-id-processor.js +182 -0
  103. package/dist/processors/collection-id-processor.js.map +1 -0
  104. package/dist/processors/collection-item-field-processor.d.ts +39 -0
  105. package/dist/processors/collection-item-field-processor.d.ts.map +1 -0
  106. package/dist/processors/collection-item-field-processor.js +289 -0
  107. package/dist/processors/collection-item-field-processor.js.map +1 -0
  108. package/dist/processors/collection-item-id-processor.d.ts +12 -0
  109. package/dist/processors/collection-item-id-processor.d.ts.map +1 -0
  110. package/dist/processors/collection-item-id-processor.js +50 -0
  111. package/dist/processors/collection-item-id-processor.js.map +1 -0
  112. package/dist/processors/static-array-processor.d.ts +28 -0
  113. package/dist/processors/static-array-processor.d.ts.map +1 -0
  114. package/dist/processors/static-array-processor.js +173 -0
  115. package/dist/processors/static-array-processor.js.map +1 -0
  116. package/dist/processors/utils/collection-tracing-utils.d.ts +36 -0
  117. package/dist/processors/utils/collection-tracing-utils.d.ts.map +1 -0
  118. package/dist/processors/utils/collection-tracing-utils.js +390 -0
  119. package/dist/processors/utils/collection-tracing-utils.js.map +1 -0
  120. package/dist/processors/utils/shared-utils.d.ts +96 -0
  121. package/dist/processors/utils/shared-utils.d.ts.map +1 -0
  122. package/dist/processors/utils/shared-utils.js +600 -0
  123. package/dist/processors/utils/shared-utils.js.map +1 -0
  124. package/dist/statics/index.mjs +16 -0
  125. package/dist/statics/index.mjs.map +1 -0
  126. package/dist/utils.d.ts +2 -0
  127. package/dist/utils.d.ts.map +1 -0
  128. package/dist/utils.js +22 -0
  129. package/dist/utils.js.map +1 -0
  130. package/dist/visual-edit-plugin.d.ts +3 -0
  131. package/dist/visual-edit-plugin.d.ts.map +1 -0
  132. package/dist/visual-edit-plugin.js +100 -0
  133. package/dist/visual-edit-plugin.js.map +1 -0
  134. package/package.json +75 -0
  135. package/src/ErrorOverlay.ts +71 -0
  136. package/src/bridge.ts +8 -0
  137. package/src/capabilities/inline-edit/controller.ts +254 -0
  138. package/src/capabilities/inline-edit/dom-utils.ts +58 -0
  139. package/src/capabilities/inline-edit/index.ts +2 -0
  140. package/src/capabilities/inline-edit/types.ts +35 -0
  141. package/src/consts.ts +11 -0
  142. package/src/error-overlay-plugin.ts +19 -0
  143. package/src/html-injections-plugin.ts +166 -0
  144. package/src/index.ts +225 -0
  145. package/src/injections/layer-dropdown/LAYERS.md +258 -0
  146. package/src/injections/layer-dropdown/consts.ts +51 -0
  147. package/src/injections/layer-dropdown/controller.ts +109 -0
  148. package/src/injections/layer-dropdown/dropdown-ui.ts +242 -0
  149. package/src/injections/layer-dropdown/types.ts +30 -0
  150. package/src/injections/layer-dropdown/utils.ts +175 -0
  151. package/src/injections/navigation-notifier.ts +43 -0
  152. package/src/injections/sandbox-hmr-notifier.ts +8 -0
  153. package/src/injections/sandbox-mount-observer.ts +25 -0
  154. package/src/injections/unhandled-errors-handlers.ts +114 -0
  155. package/src/injections/utils.ts +208 -0
  156. package/src/injections/visual-edit-agent.ts +706 -0
  157. package/src/jsx-processor.ts +169 -0
  158. package/src/jsx-utils.ts +131 -0
  159. package/src/processors/collection-id-processor.ts +261 -0
  160. package/src/processors/collection-item-field-processor.ts +439 -0
  161. package/src/processors/collection-item-id-processor.ts +69 -0
  162. package/src/processors/static-array-processor.ts +260 -0
  163. package/src/processors/utils/collection-tracing-utils.ts +507 -0
  164. package/src/processors/utils/shared-utils.ts +785 -0
  165. package/src/utils.ts +27 -0
  166. package/src/visual-edit-plugin.md +358 -0
  167. package/src/visual-edit-plugin.ts +110 -0
@@ -0,0 +1,507 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type * as t from "@babel/types";
3
+ import type { CollectionInfo } from "../../capabilities/inline-edit/types.js";
4
+ import {
5
+ ExpressionAnalysisUtils,
6
+ BindingUtils,
7
+ CallExpressionUtils,
8
+ } from "./shared-utils.js";
9
+
10
+ export class CollectionTracingUtils {
11
+ private expressionUtils: ExpressionAnalysisUtils;
12
+ private bindingUtils: BindingUtils;
13
+ private callUtils: CallExpressionUtils;
14
+ private visitedSetters = new Set<string>();
15
+ private visitedGetByIdSetters = new Set<string>();
16
+
17
+ constructor(private types: typeof t) {
18
+ this.expressionUtils = new ExpressionAnalysisUtils(types);
19
+ this.bindingUtils = new BindingUtils(types);
20
+ this.callUtils = new CallExpressionUtils(types);
21
+ }
22
+
23
+ resetVisited(): void {
24
+ this.visitedSetters.clear();
25
+ this.visitedGetByIdSetters.clear();
26
+ }
27
+
28
+ traceCollectionSource(
29
+ path: NodePath<t.Expression>
30
+ ): CollectionInfo | null {
31
+ this.resetVisited();
32
+ return this.traceExpression(path);
33
+ }
34
+
35
+ private traceExpression(
36
+ path: NodePath<t.Expression>
37
+ ): CollectionInfo | null {
38
+ if (path.isIdentifier()) {
39
+ return this.traceIdentifierToCollection(path);
40
+ }
41
+
42
+ if (path.isMemberExpression()) {
43
+ return this.traceMemberExpression(path);
44
+ }
45
+
46
+ if (path.isCallExpression()) {
47
+ return this.traceCallExpression(path);
48
+ }
49
+
50
+ if (path.isAwaitExpression()) {
51
+ const argument = path.get("argument");
52
+ if (argument.isExpression()) {
53
+ return this.traceExpression(argument);
54
+ }
55
+ }
56
+
57
+ if (path.isArrayExpression()) {
58
+ return this.traceArrayExpression(path);
59
+ }
60
+
61
+ return null;
62
+ }
63
+
64
+ private traceIdentifierToCollection(
65
+ path: NodePath<t.Identifier>
66
+ ): CollectionInfo | null {
67
+ const name = path.node.name;
68
+ const binding = path.scope.getBinding(name);
69
+ if (!binding) return null;
70
+
71
+ if (binding.path.isVariableDeclarator()) {
72
+ return this.traceVariableDeclarator(binding.path, name);
73
+ }
74
+
75
+ if (this.bindingUtils.isFunctionParameter(name, path)) {
76
+ return this.traceParameterToCollection(name, path);
77
+ }
78
+
79
+ return null;
80
+ }
81
+
82
+ private traceVariableDeclarator(
83
+ declaratorPath: NodePath<t.VariableDeclarator>,
84
+ variableName: string
85
+ ): CollectionInfo | null {
86
+ const init = declaratorPath.get("init");
87
+
88
+ if (init.isCallExpression()) {
89
+ const directResult = this.checkDirectServiceCall(init);
90
+ if (directResult) return directResult;
91
+
92
+ const useStateInfo = this.bindingUtils.isUseStateCall(init);
93
+ if (useStateInfo?.setterName) {
94
+ return this.traceUseStateSetter(useStateInfo.setterName, declaratorPath);
95
+ }
96
+ }
97
+
98
+ if (init.isAwaitExpression()) {
99
+ const awaitArg = init.get("argument");
100
+ if (awaitArg.isCallExpression()) {
101
+ const directResult = this.checkDirectServiceCall(awaitArg);
102
+ if (directResult) return directResult;
103
+ }
104
+ return this.traceExpression(init);
105
+ }
106
+
107
+ if (init.isMemberExpression()) {
108
+ return this.traceExpression(init);
109
+ }
110
+
111
+ if (init.isIdentifier()) {
112
+ return this.traceExpression(init);
113
+ }
114
+
115
+ if (init.isCallExpression()) {
116
+ return this.traceExpression(init);
117
+ }
118
+
119
+ const id = declaratorPath.get("id");
120
+
121
+ if (id.isArrayPattern()) {
122
+ return this.traceArrayDestructuring(declaratorPath, id, variableName);
123
+ }
124
+
125
+ if (id.isObjectPattern()) {
126
+ return this.traceObjectDestructuring(declaratorPath, id, variableName);
127
+ }
128
+
129
+ return null;
130
+ }
131
+
132
+ private traceUseStateSetter(
133
+ setterName: string,
134
+ declaratorPath: NodePath<t.VariableDeclarator>
135
+ ): CollectionInfo | null {
136
+ if (this.visitedSetters.has(setterName)) return null;
137
+ this.visitedSetters.add(setterName);
138
+
139
+ const functionScope = declaratorPath.getFunctionParent() ?? declaratorPath.scope.path;
140
+ const setterCall = this.bindingUtils.findSetterCallInScope(
141
+ setterName,
142
+ functionScope
143
+ );
144
+
145
+ if (!setterCall) return null;
146
+
147
+ const args = setterCall.get("arguments");
148
+ const firstArg = args[0];
149
+ if (!firstArg || !firstArg.isExpression()) return null;
150
+
151
+ return this.traceExpression(firstArg);
152
+ }
153
+
154
+ private traceMemberExpression(
155
+ path: NodePath<t.MemberExpression>
156
+ ): CollectionInfo | null {
157
+ const property = path.get("property");
158
+ const object = path.get("object");
159
+
160
+ if (
161
+ property.isIdentifier() &&
162
+ property.node.name === "items"
163
+ ) {
164
+ if (object.isExpression()) {
165
+ return this.traceExpression(object);
166
+ }
167
+ }
168
+
169
+ if (object.isIdentifier()) {
170
+ const objResult = this.traceIdentifierToCollection(object);
171
+ if (objResult && property.isIdentifier()) {
172
+ if (objResult.references.includes(property.node.name)) {
173
+ return { id: property.node.name, references: [] };
174
+ }
175
+ }
176
+ return objResult;
177
+ }
178
+
179
+ if (object.isExpression()) {
180
+ return this.traceExpression(object);
181
+ }
182
+
183
+ return null;
184
+ }
185
+
186
+ private traceCallExpression(
187
+ path: NodePath<t.CallExpression>
188
+ ): CollectionInfo | null {
189
+ const directResult = this.checkDirectServiceCall(path);
190
+ if (directResult) return directResult;
191
+
192
+ const useQueryResult = this.traceUseQueryCall(path);
193
+ if (useQueryResult) return useQueryResult;
194
+
195
+ if (this.callUtils.isChainedArrayMethod(path.node)) {
196
+ const callee = path.get("callee");
197
+ if (callee.isMemberExpression()) {
198
+ const obj = callee.get("object") as NodePath<t.Expression>;
199
+ return this.traceExpression(obj);
200
+ }
201
+ }
202
+
203
+ return null;
204
+ }
205
+
206
+ /**
207
+ * Trace useQuery({ queryFn: () => base44.entities.X.list() }) patterns.
208
+ * Extracts the collection from the queryFn return expression.
209
+ */
210
+ private traceUseQueryCall(
211
+ path: NodePath<t.CallExpression>
212
+ ): CollectionInfo | null {
213
+ const callee = path.get("callee");
214
+ if (!callee.isIdentifier() || callee.node.name !== "useQuery") return null;
215
+
216
+ const args = path.get("arguments");
217
+ const configArg = args[0];
218
+ if (!configArg?.isObjectExpression()) return null;
219
+
220
+ for (const prop of configArg.get("properties")) {
221
+ if (!prop.isObjectProperty()) continue;
222
+ const key = prop.get("key");
223
+ if (!key.isIdentifier() || key.node.name !== "queryFn") continue;
224
+
225
+ const value = prop.get("value");
226
+
227
+ if (value.isArrowFunctionExpression() || value.isFunctionExpression()) {
228
+ const fnBody = value.get("body") as NodePath<t.Node>;
229
+ if (fnBody.isCallExpression()) {
230
+ return this.checkDirectServiceCall(fnBody as NodePath<t.CallExpression>);
231
+ }
232
+ if (fnBody.isBlockStatement()) {
233
+ let result: CollectionInfo | null = null;
234
+ fnBody.traverse({
235
+ ReturnStatement: (retPath: NodePath<t.ReturnStatement>) => {
236
+ if (result) return;
237
+ const arg = retPath.get("argument");
238
+ if (arg.isCallExpression()) {
239
+ result = this.checkDirectServiceCall(arg);
240
+ }
241
+ },
242
+ });
243
+ if (result) return result;
244
+ }
245
+ }
246
+ }
247
+
248
+ return null;
249
+ }
250
+
251
+ private checkDirectServiceCall(
252
+ path: NodePath<t.CallExpression>
253
+ ): CollectionInfo | null {
254
+ const getAllInfo = this.callUtils.isGetAllCall(path.node);
255
+ if (getAllInfo) {
256
+ return {
257
+ id: getAllInfo.collectionName,
258
+ references: getAllInfo.references,
259
+ };
260
+ }
261
+
262
+ const getByIdInfo = this.callUtils.isGetByIdCall(path.node);
263
+ if (getByIdInfo) {
264
+ return {
265
+ id: getByIdInfo.collectionName,
266
+ references: getByIdInfo.multiRefFields,
267
+ };
268
+ }
269
+
270
+ const base44List = this.callUtils.isBase44EntityListCall(path.node);
271
+ if (base44List) {
272
+ return { id: base44List.collectionName, references: [] };
273
+ }
274
+
275
+ const base44Get = this.callUtils.isBase44EntityGetCall(path.node);
276
+ if (base44Get) {
277
+ return { id: base44Get.collectionName, references: [] };
278
+ }
279
+
280
+ return null;
281
+ }
282
+
283
+ private traceArrayDestructuring(
284
+ declaratorPath: NodePath<t.VariableDeclarator>,
285
+ pattern: NodePath<t.ArrayPattern>,
286
+ variableName: string
287
+ ): CollectionInfo | null {
288
+ const elements = pattern.get("elements");
289
+ const index = elements.findIndex(
290
+ (el) => el.isIdentifier() && el.node.name === variableName
291
+ );
292
+
293
+ if (index === -1) return null;
294
+
295
+ const init = declaratorPath.get("init");
296
+
297
+ if (init.hasNode() && this.bindingUtils.isPromiseAllCall(init as NodePath<t.Node>)) {
298
+ return this.tracePromiseAllElement(init as NodePath<t.Node>, index);
299
+ }
300
+
301
+ if (init.isCallExpression()) {
302
+ const useStateInfo = this.bindingUtils.isUseStateCall(init);
303
+ if (useStateInfo && index === 0 && useStateInfo.setterName) {
304
+ return this.traceUseStateSetter(useStateInfo.setterName, declaratorPath);
305
+ }
306
+ }
307
+
308
+ return null;
309
+ }
310
+
311
+ private traceObjectDestructuring(
312
+ declaratorPath: NodePath<t.VariableDeclarator>,
313
+ pattern: NodePath<t.ObjectPattern>,
314
+ variableName: string
315
+ ): CollectionInfo | null {
316
+ const init = declaratorPath.get("init");
317
+ if (!init.isExpression()) return null;
318
+
319
+ const prop = pattern.node.properties.find(
320
+ (p) =>
321
+ this.types.isObjectProperty(p) &&
322
+ (
323
+ (this.types.isIdentifier(p.value) && p.value.name === variableName) ||
324
+ (this.types.isAssignmentPattern(p.value) &&
325
+ this.types.isIdentifier(p.value.left) &&
326
+ p.value.left.name === variableName)
327
+ )
328
+ );
329
+
330
+ if (!prop || !this.types.isObjectProperty(prop)) return null;
331
+
332
+ const key = prop.key;
333
+ const propertyName = this.types.isIdentifier(key)
334
+ ? key.name
335
+ : this.types.isStringLiteral(key)
336
+ ? key.value
337
+ : null;
338
+
339
+ if (propertyName === "items") {
340
+ return this.traceExpression(init);
341
+ }
342
+
343
+ return this.traceExpression(init);
344
+ }
345
+
346
+ private tracePromiseAllElement(
347
+ init: NodePath<t.Node>,
348
+ index: number
349
+ ): CollectionInfo | null {
350
+ let callExpr: NodePath<t.CallExpression>;
351
+
352
+ if (init.isAwaitExpression()) {
353
+ const arg = init.get("argument");
354
+ if (!arg.isCallExpression()) return null;
355
+ callExpr = arg;
356
+ } else if (init.isCallExpression()) {
357
+ callExpr = init;
358
+ } else {
359
+ return null;
360
+ }
361
+
362
+ const args = callExpr.get("arguments");
363
+ const firstArg = args[0];
364
+ if (!firstArg?.isArrayExpression()) return null;
365
+
366
+ const elements = firstArg.get("elements");
367
+ const targetElement = elements[index];
368
+ if (!targetElement || !targetElement.isExpression()) return null;
369
+
370
+ return this.traceExpression(targetElement);
371
+ }
372
+
373
+ private traceParameterToCollection(
374
+ paramName: string,
375
+ path: NodePath
376
+ ): CollectionInfo | null {
377
+ const fn = path.getFunctionParent();
378
+ if (!fn) return null;
379
+
380
+ const fnName = this.getFunctionName(fn);
381
+ if (!fnName) return null;
382
+
383
+ const programPath = fn.findParent((p) => p.isProgram());
384
+ if (!programPath) return null;
385
+
386
+ let result: CollectionInfo | null = null;
387
+
388
+ programPath.traverse({
389
+ JSXOpeningElement: (jsxPath: NodePath<t.JSXOpeningElement>) => {
390
+ if (result) return;
391
+
392
+ const elementName = this.getJSXElementName(jsxPath.node);
393
+ if (elementName !== fnName) return;
394
+
395
+ for (const attr of jsxPath.node.attributes) {
396
+ if (!this.types.isJSXAttribute(attr)) continue;
397
+ if (!this.types.isJSXIdentifier(attr.name)) continue;
398
+ if (attr.name.name !== paramName) continue;
399
+
400
+ if (
401
+ attr.value &&
402
+ this.types.isJSXExpressionContainer(attr.value) &&
403
+ this.types.isExpression(attr.value.expression)
404
+ ) {
405
+ const exprPath = jsxPath
406
+ .get("attributes")
407
+ .find(
408
+ (a) =>
409
+ a.isJSXAttribute() &&
410
+ this.types.isJSXIdentifier(a.node.name) &&
411
+ a.node.name.name === paramName
412
+ );
413
+
414
+ if (exprPath && exprPath.isJSXAttribute()) {
415
+ const valPath = exprPath.get("value");
416
+ if (
417
+ valPath.isJSXExpressionContainer()
418
+ ) {
419
+ const expr = valPath.get("expression");
420
+ if (expr.isExpression()) {
421
+ result = this.traceExpression(expr);
422
+ }
423
+ }
424
+ }
425
+ }
426
+ }
427
+ },
428
+ });
429
+
430
+ if (!result) {
431
+ return { id: paramName, references: [] };
432
+ }
433
+
434
+ return result;
435
+ }
436
+
437
+ private traceArrayExpression(
438
+ path: NodePath<t.ArrayExpression>
439
+ ): CollectionInfo | null {
440
+ const elements = path.get("elements");
441
+ for (const el of elements) {
442
+ if (el.isSpreadElement()) {
443
+ const arg = el.get("argument");
444
+ if (arg.isExpression()) {
445
+ const result = this.traceExpression(arg);
446
+ if (result) return result;
447
+ }
448
+ }
449
+ }
450
+ return null;
451
+ }
452
+
453
+ private getFunctionName(fn: NodePath<t.Function>): string | null {
454
+ if (fn.isFunctionDeclaration() && fn.node.id) {
455
+ return fn.node.id.name;
456
+ }
457
+
458
+ const parent = fn.parentPath;
459
+ if (parent?.isVariableDeclarator()) {
460
+ const id = parent.get("id");
461
+ if (id.isIdentifier()) return id.node.name;
462
+ }
463
+
464
+ return null;
465
+ }
466
+
467
+ private getJSXElementName(node: t.JSXOpeningElement): string | null {
468
+ if (this.types.isJSXIdentifier(node.name)) {
469
+ return node.name.name;
470
+ }
471
+ return null;
472
+ }
473
+
474
+ traceGetByIdSource(
475
+ path: NodePath
476
+ ): CollectionInfo | null {
477
+ this.visitedGetByIdSetters.clear();
478
+ return this.findGetByIdInScope(path);
479
+ }
480
+
481
+ private findGetByIdInScope(
482
+ path: NodePath
483
+ ): CollectionInfo | null {
484
+ const fn = path.getFunctionParent() ?? path.scope.path;
485
+ let result: CollectionInfo | null = null;
486
+
487
+ fn.traverse({
488
+ CallExpression: (callPath: NodePath<t.CallExpression>) => {
489
+ if (result) return;
490
+ const info = this.callUtils.isGetByIdCall(callPath.node);
491
+ if (info) {
492
+ result = {
493
+ id: info.collectionName,
494
+ references: info.multiRefFields,
495
+ };
496
+ return;
497
+ }
498
+ const base44Get = this.callUtils.isBase44EntityGetCall(callPath.node);
499
+ if (base44Get) {
500
+ result = { id: base44Get.collectionName, references: [] };
501
+ }
502
+ },
503
+ });
504
+
505
+ return result;
506
+ }
507
+ }