vue3-migration 1.3.0 → 1.3.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue3-migration",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Automatically migrate Vue 2 mixins to Vue 3 composables — data, computed, methods, watchers, lifecycle hooks, and all",
5
5
  "bin": {
6
6
  "vue3-migration": "./bin/cli.js"
@@ -34,8 +34,9 @@ def extract_all_identifiers(source: str) -> list[str]:
34
34
  else:
35
35
  ids.add(part.split("=")[0].strip())
36
36
 
37
- # Return keys: return { foo, bar, baz: val }
38
- ret = re.search(r"\breturn\s*\{", source)
37
+ # Return keys: return { foo, bar, baz: val } — use LAST match to skip nested returns
38
+ ret_matches = list(re.finditer(r"\breturn\s*\{", source))
39
+ ret = ret_matches[-1] if ret_matches else None
39
40
  if ret:
40
41
  block = extract_brace_block(source, ret.end() - 1)
41
42
  ids.update(re.findall(r"\b(\w+)\s*[,}\n:]", block))
@@ -59,8 +60,9 @@ def extract_return_keys(source: str) -> list[str]:
59
60
  "null", "undefined", "new", "value",
60
61
  }
61
62
 
62
- # Case 1: direct return { ... }
63
- ret = re.search(r"\breturn\s*\{", source)
63
+ # Case 1: direct return { ... } — use LAST match to skip nested returns
64
+ matches = list(re.finditer(r"\breturn\s*\{", source))
65
+ ret = matches[-1] if matches else None
64
66
  if ret:
65
67
  block = extract_brace_block(source, ret.end() - 1)
66
68
  keys = re.findall(r"\b(\w+)\b", block)
@@ -18,7 +18,7 @@ from ..core.mixin_analyzer import (
18
18
  extract_lifecycle_hooks, extract_mixin_members,
19
19
  find_external_this_refs,
20
20
  )
21
- from ..core.warning_collector import collect_mixin_warnings
21
+ from ..core.warning_collector import collect_mixin_warnings, detect_name_collisions
22
22
  from ..models import (
23
23
  ComposableCoverage, FileChange, MigrationConfig, MigrationPlan, MigrationStatus,
24
24
  MixinEntry, MixinMembers,
@@ -336,6 +336,20 @@ def plan_component_injections(
336
336
  if not ready_entries:
337
337
  continue
338
338
 
339
+ # Detect member name collisions across composables for this component
340
+ if len(ready_entries) > 1:
341
+ composable_members_map = {}
342
+ for entry in ready_entries:
343
+ if entry.composable and entry.classification:
344
+ composable_members_map[entry.composable.fn_name] = list(
345
+ entry.classification.injectable
346
+ )
347
+ collision_warnings = detect_name_collisions(composable_members_map)
348
+ if collision_warnings:
349
+ for w in collision_warnings:
350
+ w.mixin_stem = "cross-composable"
351
+ ready_entries[0].warnings.extend(collision_warnings)
352
+
339
353
  content = comp_source
340
354
  changes_desc = []
341
355
 
@@ -447,6 +461,11 @@ def run_scoped(
447
461
 
448
462
  Exactly one of component_path or mixin_stem must be provided.
449
463
  No file I/O. Returns a MigrationPlan the CLI can show as a diff and write.
464
+
465
+ Note: When component_path is provided, composable patches only aggregate
466
+ requirements from that component's entries. Shared composables may receive
467
+ incomplete patches. Use mixin_stem scope or full-project run for complete
468
+ composable coverage.
450
469
  """
451
470
  if component_path is None and mixin_stem is None:
452
471
  raise ValueError("Provide either component_path or mixin_stem")