@base44-preview/vite-plugin 0.2.25-pr.36.792e85b → 0.2.26-pr.43.056eecd

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/consts.d.ts +13 -0
  2. package/dist/consts.d.ts.map +1 -0
  3. package/dist/consts.js +13 -0
  4. package/dist/consts.js.map +1 -0
  5. package/dist/jsx-processor.d.ts +10 -1
  6. package/dist/jsx-processor.d.ts.map +1 -1
  7. package/dist/jsx-processor.js +47 -5
  8. package/dist/jsx-processor.js.map +1 -1
  9. package/dist/jsx-utils.d.ts +9 -0
  10. package/dist/jsx-utils.d.ts.map +1 -1
  11. package/dist/jsx-utils.js +86 -0
  12. package/dist/jsx-utils.js.map +1 -1
  13. package/dist/processors/collection-id-processor.d.ts +20 -0
  14. package/dist/processors/collection-id-processor.d.ts.map +1 -0
  15. package/dist/processors/collection-id-processor.js +182 -0
  16. package/dist/processors/collection-id-processor.js.map +1 -0
  17. package/dist/processors/collection-item-field-processor.d.ts +22 -0
  18. package/dist/processors/collection-item-field-processor.d.ts.map +1 -0
  19. package/dist/processors/collection-item-field-processor.js +215 -0
  20. package/dist/processors/collection-item-field-processor.js.map +1 -0
  21. package/dist/processors/collection-item-id-processor.d.ts +12 -0
  22. package/dist/processors/collection-item-id-processor.d.ts.map +1 -0
  23. package/dist/processors/collection-item-id-processor.js +50 -0
  24. package/dist/processors/collection-item-id-processor.js.map +1 -0
  25. package/dist/processors/collection-reference-field-processor.d.ts +31 -0
  26. package/dist/processors/collection-reference-field-processor.d.ts.map +1 -0
  27. package/dist/processors/collection-reference-field-processor.js +174 -0
  28. package/dist/processors/collection-reference-field-processor.js.map +1 -0
  29. package/dist/processors/collection-tracing-utils.d.ts +31 -0
  30. package/dist/processors/collection-tracing-utils.d.ts.map +1 -0
  31. package/dist/processors/collection-tracing-utils.js +326 -0
  32. package/dist/processors/collection-tracing-utils.js.map +1 -0
  33. package/dist/processors/shared-utils.d.ts +64 -0
  34. package/dist/processors/shared-utils.d.ts.map +1 -1
  35. package/dist/processors/shared-utils.js +464 -0
  36. package/dist/processors/shared-utils.js.map +1 -1
  37. package/dist/processors/static-array-processor.d.ts +2 -3
  38. package/dist/processors/static-array-processor.d.ts.map +1 -1
  39. package/dist/processors/static-array-processor.js +2 -3
  40. package/dist/processors/static-array-processor.js.map +1 -1
  41. package/dist/types.d.ts +5 -0
  42. package/dist/types.d.ts.map +1 -0
  43. package/dist/types.js +2 -0
  44. package/dist/types.js.map +1 -0
  45. package/dist/visual-edit-plugin.d.ts +0 -1
  46. package/dist/visual-edit-plugin.d.ts.map +1 -1
  47. package/dist/visual-edit-plugin.js +29 -178
  48. package/dist/visual-edit-plugin.js.map +1 -1
  49. package/package.json +1 -1
  50. package/src/consts.ts +14 -0
  51. package/src/jsx-processor.ts +58 -9
  52. package/src/jsx-utils.ts +116 -0
  53. package/src/processors/collection-id-processor.ts +261 -0
  54. package/src/processors/collection-item-field-processor.ts +321 -0
  55. package/src/processors/collection-item-id-processor.ts +69 -0
  56. package/src/processors/collection-reference-field-processor.ts +225 -0
  57. package/src/processors/collection-tracing-utils.ts +436 -0
  58. package/src/processors/shared-utils.ts +595 -0
  59. package/src/processors/static-array-processor.ts +6 -3
  60. package/src/types.ts +4 -0
  61. package/src/visual-edit-plugin.ts +34 -215
@@ -1,6 +1,7 @@
1
1
  import type { NodePath } from "@babel/traverse";
2
2
  import type * as t from "@babel/types";
3
3
  import { JSXUtils } from "../jsx-utils.js";
4
+ import { ALLOWED_CUSTOM_COMPONENTS, EXCLUDED_FIELDS } from "../consts.js";
4
5
 
5
6
  export class JSXAttributeUtils {
6
7
  constructor(private types: typeof t) {}
@@ -16,6 +17,32 @@ export class JSXAttributeUtils {
16
17
  );
17
18
  }
18
19
 
20
+ getAttributeValue(
21
+ path: NodePath<t.JSXOpeningElement>,
22
+ attributeName: string
23
+ ): t.JSXAttribute["value"] | null {
24
+ for (const attr of path.node.attributes) {
25
+ if (
26
+ this.types.isJSXAttribute(attr) &&
27
+ JSXUtils.getAttributeName(attr) === attributeName
28
+ ) {
29
+ return attr.value;
30
+ }
31
+ }
32
+ return null;
33
+ }
34
+
35
+ getAttributeStringValue(
36
+ path: NodePath<t.JSXOpeningElement>,
37
+ attributeName: string
38
+ ): string | null {
39
+ const value = this.getAttributeValue(path, attributeName);
40
+ if (value && this.types.isStringLiteral(value)) {
41
+ return value.value;
42
+ }
43
+ return null;
44
+ }
45
+
19
46
  addStringAttribute(
20
47
  path: NodePath<t.JSXOpeningElement>,
21
48
  attributeName: string,
@@ -45,6 +72,475 @@ export class JSXAttributeUtils {
45
72
  );
46
73
  }
47
74
  }
75
+
76
+ findAncestorWithAttribute(
77
+ path: NodePath,
78
+ attributeName: string
79
+ ): NodePath<t.JSXOpeningElement> | null {
80
+ let current: NodePath | null = path.parentPath;
81
+ while (current) {
82
+ if (current.isJSXElement()) {
83
+ const opening = current.get("openingElement");
84
+ if (this.hasAttribute(opening, attributeName)) {
85
+ return opening;
86
+ }
87
+ }
88
+ current = current.parentPath;
89
+ }
90
+ return null;
91
+ }
92
+ }
93
+
94
+ export class PathNavigationUtils {
95
+ constructor(private types: typeof t) {}
96
+
97
+ findParentJSXElement(
98
+ path: NodePath
99
+ ): NodePath<t.JSXElement> | null {
100
+ let current: NodePath | null = path.parentPath;
101
+ while (current) {
102
+ if (current.isJSXElement()) return current;
103
+ current = current.parentPath;
104
+ }
105
+ return null;
106
+ }
107
+
108
+ findEnclosingFunction(
109
+ path: NodePath
110
+ ): NodePath<t.Function> | null {
111
+ let current: NodePath | null = path.parentPath;
112
+ while (current) {
113
+ if (current.isFunction()) return current as NodePath<t.Function>;
114
+ current = current.parentPath;
115
+ }
116
+ return null;
117
+ }
118
+
119
+ findReturnStatement(
120
+ path: NodePath
121
+ ): NodePath<t.ReturnStatement> | null {
122
+ let current: NodePath | null = path.parentPath;
123
+ while (current) {
124
+ if (current.isReturnStatement()) return current;
125
+ current = current.parentPath;
126
+ }
127
+ return null;
128
+ }
129
+
130
+ isRootReturnElement(
131
+ path: NodePath<t.JSXOpeningElement>
132
+ ): boolean {
133
+ const jsxElement = path.parentPath;
134
+ if (!jsxElement?.isJSXElement()) return false;
135
+
136
+ const parent = jsxElement.parentPath;
137
+ if (!parent) return false;
138
+
139
+ if (parent.isReturnStatement()) return true;
140
+
141
+ if (parent.isArrowFunctionExpression()) return true;
142
+
143
+ if (parent.isParenthesizedExpression()) {
144
+ const grandparent = parent.parentPath;
145
+ if (grandparent?.isReturnStatement()) return true;
146
+ if (grandparent?.isArrowFunctionExpression()) return true;
147
+ }
148
+
149
+ return false;
150
+ }
151
+
152
+ findDOMElementTarget(
153
+ path: NodePath<t.JSXOpeningElement>
154
+ ): NodePath<t.JSXOpeningElement> | null {
155
+ if (this.isDOMOrAllowedElement(path)) return path;
156
+
157
+ let current: NodePath | null = path.parentPath;
158
+ while (current) {
159
+ if (current.isJSXElement()) {
160
+ const opening = current.get("openingElement");
161
+ if (this.isDOMOrAllowedElement(opening)) return opening;
162
+ }
163
+ current = current.parentPath;
164
+ }
165
+ return null;
166
+ }
167
+
168
+ private isDOMOrAllowedElement(
169
+ path: NodePath<t.JSXOpeningElement>
170
+ ): boolean {
171
+ const name = JSXUtils.getElementName(path.node);
172
+ if (!name) return false;
173
+
174
+ if (name.charAt(0) === name.charAt(0).toLowerCase()) return true;
175
+
176
+ return ALLOWED_CUSTOM_COMPONENTS.includes(name);
177
+ }
178
+ }
179
+
180
+ export class ExpressionAnalysisUtils {
181
+ constructor(private types: typeof t) {}
182
+
183
+ isIdAccess(node: t.Expression): boolean {
184
+ return (
185
+ this.types.isMemberExpression(node) &&
186
+ ((this.types.isIdentifier(node.property) &&
187
+ node.property.name === "_id") ||
188
+ (this.types.isStringLiteral(node.property) &&
189
+ node.property.value === "_id"))
190
+ );
191
+ }
192
+
193
+ isItemsAccess(node: t.Expression): boolean {
194
+ return (
195
+ this.types.isMemberExpression(node) &&
196
+ this.types.isIdentifier(node.property) &&
197
+ node.property.name === "items"
198
+ );
199
+ }
200
+
201
+ isLengthAccess(node: t.Expression): boolean {
202
+ return (
203
+ this.types.isMemberExpression(node) &&
204
+ this.types.isIdentifier(node.property) &&
205
+ node.property.name === "length"
206
+ );
207
+ }
208
+
209
+ extractRootIdentifier(node: t.Expression): t.Identifier | null {
210
+ if (this.types.isIdentifier(node)) return node;
211
+ if (this.types.isMemberExpression(node)) {
212
+ return this.extractRootIdentifier(node.object as t.Expression);
213
+ }
214
+ if (this.types.isOptionalMemberExpression(node)) {
215
+ return this.extractRootIdentifier(node.object as t.Expression);
216
+ }
217
+ if (this.types.isCallExpression(node) && this.types.isMemberExpression(node.callee)) {
218
+ return this.extractRootIdentifier(node.callee.object as t.Expression);
219
+ }
220
+ return null;
221
+ }
222
+
223
+ unwrapLogicalExpression(node: t.Expression): t.Expression {
224
+ if (this.types.isLogicalExpression(node)) {
225
+ if (node.operator === "&&") return node.right as t.Expression;
226
+ if (node.operator === "||" || node.operator === "??") {
227
+ return node.left as t.Expression;
228
+ }
229
+ }
230
+ return node;
231
+ }
232
+
233
+ collectMemberExpressionPath(node: t.Expression): string[] {
234
+ const parts: string[] = [];
235
+ let current: t.Expression = node;
236
+
237
+ while (
238
+ this.types.isMemberExpression(current) ||
239
+ this.types.isOptionalMemberExpression(current)
240
+ ) {
241
+ const prop = (current as t.MemberExpression).property;
242
+ if (this.types.isIdentifier(prop)) {
243
+ parts.unshift(prop.name);
244
+ } else if (this.types.isStringLiteral(prop)) {
245
+ parts.unshift(prop.value);
246
+ }
247
+ current = (current as t.MemberExpression).object as t.Expression;
248
+ }
249
+
250
+ if (this.types.isIdentifier(current)) {
251
+ parts.unshift(current.name);
252
+ }
253
+
254
+ return parts;
255
+ }
256
+
257
+ createOptionalChainExpression(
258
+ node: t.MemberExpression
259
+ ): t.OptionalMemberExpression {
260
+ const object = this.types.isOptionalMemberExpression(node.object)
261
+ ? node.object
262
+ : this.types.isMemberExpression(node.object)
263
+ ? this.createOptionalChainExpression(node.object)
264
+ : node.object;
265
+
266
+ const property = node.property as t.Expression;
267
+
268
+ return this.types.optionalMemberExpression(
269
+ object,
270
+ property,
271
+ node.computed,
272
+ true
273
+ );
274
+ }
275
+
276
+ getFieldPathFromExpression(
277
+ node: t.Expression,
278
+ rootName: string
279
+ ): string | null {
280
+ const parts = this.collectMemberExpressionPath(node);
281
+ if (parts.length < 2) return null;
282
+ if (parts[0] !== rootName) return null;
283
+
284
+ const fieldParts = parts.slice(1);
285
+ const fieldPath = fieldParts.join(".");
286
+
287
+ if (EXCLUDED_FIELDS.includes(fieldPath)) return null;
288
+ return fieldPath;
289
+ }
290
+ }
291
+
292
+ export class BindingUtils {
293
+ constructor(private types: typeof t) {}
294
+
295
+ isFunctionParameter(
296
+ identifierName: string,
297
+ path: NodePath
298
+ ): boolean {
299
+ const fn = path.getFunctionParent();
300
+ if (!fn) return false;
301
+
302
+ const params = fn.get("params");
303
+ for (const param of (Array.isArray(params) ? params : [params])) {
304
+ if (param.isIdentifier() && param.node.name === identifierName) {
305
+ return true;
306
+ }
307
+ if (param.isObjectPattern()) {
308
+ for (const prop of param.get("properties")) {
309
+ if (
310
+ prop.isObjectProperty() &&
311
+ this.types.isIdentifier(prop.node.value) &&
312
+ prop.node.value.name === identifierName
313
+ ) {
314
+ return true;
315
+ }
316
+ }
317
+ }
318
+ if (param.isArrayPattern()) {
319
+ for (const el of param.get("elements")) {
320
+ if (el.isIdentifier() && el.node.name === identifierName) {
321
+ return true;
322
+ }
323
+ }
324
+ }
325
+ }
326
+ return false;
327
+ }
328
+
329
+ isUseStateCall(
330
+ init: NodePath<t.Node>
331
+ ): { stateIndex: number; setterName: string | null } | null {
332
+ if (!init.isCallExpression()) return null;
333
+
334
+ const callee = init.get("callee");
335
+ if (!callee.isIdentifier() || callee.node.name !== "useState") return null;
336
+
337
+ const declarator = init.parentPath;
338
+ if (!declarator?.isVariableDeclarator()) return null;
339
+
340
+ const id = declarator.get("id");
341
+ if (!id.isArrayPattern()) return null;
342
+
343
+ const elements = id.get("elements");
344
+ const setterEl = elements[1];
345
+ const setterName =
346
+ setterEl && setterEl.isIdentifier() ? setterEl.node.name : null;
347
+
348
+ return { stateIndex: 0, setterName };
349
+ }
350
+
351
+ isPromiseAllCall(
352
+ init: NodePath<t.Node>
353
+ ): boolean {
354
+ if (!init.isAwaitExpression()) {
355
+ if (init.isCallExpression()) {
356
+ const callee = init.get("callee");
357
+ return this.isPromiseAllCallee(callee);
358
+ }
359
+ return false;
360
+ }
361
+
362
+ const argument = init.get("argument");
363
+ if (!argument.isCallExpression()) return false;
364
+
365
+ const callee = argument.get("callee");
366
+ return this.isPromiseAllCallee(callee);
367
+ }
368
+
369
+ private isPromiseAllCallee(callee: NodePath): boolean {
370
+ if (!callee.isMemberExpression()) return false;
371
+ const obj = callee.get("object") as NodePath;
372
+ const prop = callee.get("property") as NodePath;
373
+ return (
374
+ obj.isIdentifier() &&
375
+ obj.node.name === "Promise" &&
376
+ prop.isIdentifier() &&
377
+ prop.node.name === "all"
378
+ );
379
+ }
380
+
381
+ extractDestructuredProperties(
382
+ pattern: t.ObjectPattern
383
+ ): string[] {
384
+ const properties: string[] = [];
385
+ for (const prop of pattern.properties) {
386
+ if (this.types.isObjectProperty(prop)) {
387
+ if (this.types.isIdentifier(prop.key)) {
388
+ properties.push(prop.key.name);
389
+ } else if (this.types.isStringLiteral(prop.key)) {
390
+ properties.push(prop.key.value);
391
+ }
392
+ }
393
+ }
394
+ return properties;
395
+ }
396
+
397
+ findSetterCallInScope(
398
+ setterName: string,
399
+ scope: NodePath
400
+ ): NodePath<t.CallExpression> | null {
401
+ let result: NodePath<t.CallExpression> | null = null;
402
+
403
+ scope.traverse({
404
+ CallExpression(callPath) {
405
+ if (result) return;
406
+ const callee = callPath.get("callee");
407
+ if (callee.isIdentifier() && callee.node.name === setterName) {
408
+ result = callPath;
409
+ }
410
+ },
411
+ });
412
+
413
+ return result;
414
+ }
415
+ }
416
+
417
+ export class CallExpressionUtils {
418
+ constructor(private types: typeof t) {}
419
+
420
+ isGetAllCall(
421
+ node: t.CallExpression
422
+ ): { collectionName: string; references: string[] } | null {
423
+ const callee = node.callee;
424
+ if (!this.types.isMemberExpression(callee)) return null;
425
+
426
+ const obj = callee.object;
427
+ const prop = callee.property;
428
+
429
+ if (
430
+ !this.types.isIdentifier(obj) ||
431
+ obj.name !== "BaseCrudService" ||
432
+ !this.types.isIdentifier(prop) ||
433
+ prop.name !== "getAll"
434
+ ) {
435
+ return null;
436
+ }
437
+
438
+ const args = node.arguments;
439
+ if (args.length < 1) return null;
440
+
441
+ const firstArg = args[0];
442
+ if (!this.types.isStringLiteral(firstArg)) return null;
443
+
444
+ const collectionName = firstArg.value;
445
+ const references = this.extractReferencesFromArg(args[1]);
446
+
447
+ return { collectionName, references };
448
+ }
449
+
450
+ isGetByIdCall(
451
+ node: t.CallExpression
452
+ ): {
453
+ collectionName: string;
454
+ multiRefFields: string[];
455
+ } | null {
456
+ const callee = node.callee;
457
+ if (!this.types.isMemberExpression(callee)) return null;
458
+
459
+ const obj = callee.object;
460
+ const prop = callee.property;
461
+
462
+ if (
463
+ !this.types.isIdentifier(obj) ||
464
+ obj.name !== "BaseCrudService" ||
465
+ !this.types.isIdentifier(prop) ||
466
+ prop.name !== "getById"
467
+ ) {
468
+ return null;
469
+ }
470
+
471
+ const args = node.arguments;
472
+ if (args.length < 1) return null;
473
+
474
+ const firstArg = args[0];
475
+ if (!this.types.isStringLiteral(firstArg)) return null;
476
+
477
+ const collectionName = firstArg.value;
478
+ const multiRefFields = this.extractMultiRefFromOptions(args[2]);
479
+
480
+ return { collectionName, multiRefFields };
481
+ }
482
+
483
+ private extractReferencesFromArg(
484
+ arg: t.Expression | t.SpreadElement | t.ArgumentPlaceholder | undefined
485
+ ): string[] {
486
+ if (!arg || !this.types.isArrayExpression(arg)) return [];
487
+
488
+ return arg.elements
489
+ .filter((el): el is t.StringLiteral => this.types.isStringLiteral(el))
490
+ .map((el) => el.value);
491
+ }
492
+
493
+ private extractMultiRefFromOptions(
494
+ arg: t.Expression | t.SpreadElement | t.ArgumentPlaceholder | undefined
495
+ ): string[] {
496
+ if (!arg || !this.types.isObjectExpression(arg)) return [];
497
+
498
+ for (const prop of arg.properties) {
499
+ if (
500
+ this.types.isObjectProperty(prop) &&
501
+ this.types.isIdentifier(prop.key) &&
502
+ prop.key.name === "multiRef" &&
503
+ this.types.isArrayExpression(prop.value)
504
+ ) {
505
+ return prop.value.elements
506
+ .filter((el): el is t.StringLiteral =>
507
+ this.types.isStringLiteral(el)
508
+ )
509
+ .map((el) => el.value);
510
+ }
511
+ }
512
+ return [];
513
+ }
514
+
515
+ isArrayMethod(
516
+ node: t.CallExpression,
517
+ methodName: string
518
+ ): boolean {
519
+ const callee = node.callee;
520
+ return (
521
+ this.types.isMemberExpression(callee) &&
522
+ this.types.isIdentifier(callee.property) &&
523
+ callee.property.name === methodName
524
+ );
525
+ }
526
+
527
+ isChainedArrayMethod(node: t.CallExpression): boolean {
528
+ const chainMethods = ["filter", "sort", "slice", "concat", "reverse", "flat"];
529
+ return chainMethods.some((m) => this.isArrayMethod(node, m));
530
+ }
531
+
532
+ getCallbackArgument(
533
+ callExpr: t.CallExpression
534
+ ): t.ArrowFunctionExpression | t.FunctionExpression | null {
535
+ const firstArg = callExpr.arguments[0];
536
+ if (
537
+ this.types.isArrowFunctionExpression(firstArg) ||
538
+ this.types.isFunctionExpression(firstArg)
539
+ ) {
540
+ return firstArg;
541
+ }
542
+ return null;
543
+ }
48
544
  }
49
545
 
50
546
  export class StaticValueUtils {
@@ -113,4 +609,103 @@ export class StaticValueUtils {
113
609
  return this.isStaticValue(element as unknown as NodePath<t.Node>, visited);
114
610
  });
115
611
  }
612
+
613
+ isDerivedFromStaticData(
614
+ identifierName: string,
615
+ path: NodePath
616
+ ): boolean {
617
+ const binding = path.scope.getBinding(identifierName);
618
+ if (!binding) return false;
619
+
620
+ if (binding.path.isVariableDeclarator()) {
621
+ const init = binding.path.get("init");
622
+ if (init.isArrayExpression() || init.isObjectExpression()) {
623
+ return this.isStaticValue(init as NodePath<t.Node>);
624
+ }
625
+ }
626
+
627
+ const fnParent = path.getFunctionParent();
628
+ if (!fnParent) return false;
629
+
630
+ const params = fnParent.get("params");
631
+ for (const param of (Array.isArray(params) ? params : [params])) {
632
+ if (param.isIdentifier() && param.node.name === identifierName) {
633
+ const mapCall = fnParent.parentPath;
634
+ if (mapCall?.isCallExpression()) {
635
+ const callee = mapCall.get("callee");
636
+ if (
637
+ callee.isMemberExpression() &&
638
+ (callee.get("property") as NodePath).isIdentifier()
639
+ ) {
640
+ const propName = ((callee.get("property") as NodePath).node as t.Identifier).name;
641
+ if (propName === "map" || propName === "flatMap") {
642
+ const arrayObj = callee.get("object") as NodePath<t.Expression>;
643
+ if (arrayObj.isIdentifier()) {
644
+ return this.isDerivedFromStaticData(arrayObj.node.name, arrayObj);
645
+ }
646
+ if (arrayObj.isArrayExpression()) {
647
+ return this.isStaticArrayExpression(arrayObj);
648
+ }
649
+ }
650
+ }
651
+ }
652
+ }
653
+ }
654
+
655
+ return false;
656
+ }
657
+ }
658
+
659
+ export class TypeCheckUtils {
660
+ constructor(private types: typeof t) {}
661
+
662
+ isArrayIsArrayCheck(node: t.Expression): boolean {
663
+ if (!this.types.isCallExpression(node)) return false;
664
+
665
+ const callee = node.callee;
666
+ return (
667
+ this.types.isMemberExpression(callee) &&
668
+ this.types.isIdentifier(callee.object) &&
669
+ callee.object.name === "Array" &&
670
+ this.types.isIdentifier(callee.property) &&
671
+ callee.property.name === "isArray"
672
+ );
673
+ }
674
+
675
+ isTypeofObjectCheck(node: t.Expression): boolean {
676
+ if (!this.types.isBinaryExpression(node)) return false;
677
+ if (node.operator !== "===" && node.operator !== "==") return false;
678
+
679
+ const isTypeof = (side: t.Expression) =>
680
+ this.types.isUnaryExpression(side) && side.operator === "typeof";
681
+ const isObjectString = (side: t.Expression) =>
682
+ this.types.isStringLiteral(side) && side.value === "object";
683
+
684
+ return (
685
+ (isTypeof(node.left as t.Expression) &&
686
+ isObjectString(node.right as t.Expression)) ||
687
+ (isObjectString(node.left as t.Expression) &&
688
+ isTypeof(node.right as t.Expression))
689
+ );
690
+ }
691
+
692
+ isReferenceTypeCheck(node: t.Expression): boolean {
693
+ return this.isArrayIsArrayCheck(node) || this.isTypeofObjectCheck(node);
694
+ }
695
+
696
+ isLengthCheck(node: t.Expression): boolean {
697
+ if (this.types.isMemberExpression(node)) {
698
+ return (
699
+ this.types.isIdentifier(node.property) &&
700
+ node.property.name === "length"
701
+ );
702
+ }
703
+ if (this.types.isOptionalMemberExpression(node)) {
704
+ return (
705
+ this.types.isIdentifier(node.property) &&
706
+ node.property.name === "length"
707
+ );
708
+ }
709
+ return false;
710
+ }
116
711
  }
@@ -1,10 +1,13 @@
1
1
  import type { NodePath } from "@babel/traverse";
2
2
  import type * as t from "@babel/types";
3
+ import {
4
+ DATA_ARR_INDEX,
5
+ DATA_ARR_VARIABLE_NAME,
6
+ DATA_ARR_FIELD,
7
+ } from "../consts.js";
3
8
  import { JSXAttributeUtils, StaticValueUtils } from "./shared-utils.js";
4
9
 
5
- export const DATA_ARR_INDEX = "data-arr-index";
6
- export const DATA_ARR_VARIABLE_NAME = "data-arr-variable-name";
7
- export const DATA_ARR_FIELD = "data-arr-field";
10
+ export { DATA_ARR_INDEX, DATA_ARR_VARIABLE_NAME, DATA_ARR_FIELD };
8
11
  const GENERATED_INDEX_PARAM = "__arrIdx__";
9
12
 
10
13
  interface ArrayMapInfo {
package/src/types.ts ADDED
@@ -0,0 +1,4 @@
1
+ export interface CollectionInfo {
2
+ id: string;
3
+ references: string[];
4
+ }