@oamm/textor 1.0.14 → 1.0.16

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/README.md CHANGED
@@ -276,6 +276,8 @@ Adopt untracked files into Textor's state and add the Textor signature to them.
276
276
 
277
277
  ```bash
278
278
  pnpm textor adopt <path-or-identifier> [options]
279
+ pnpm textor adopt component <name> [options]
280
+ pnpm textor adopt feature <path> <name> [options]
279
281
  ```
280
282
 
281
283
  **Options:**
@@ -287,6 +289,12 @@ pnpm textor adopt <path-or-identifier> [options]
287
289
  # Adopt a specific component directory
288
290
  pnpm textor adopt src/components/MyNewButton
289
291
 
292
+ # Adopt a component by its name
293
+ pnpm textor adopt component MyNewButton
294
+
295
+ # Adopt a directory as a new feature (moves files to src/features/my-feat)
296
+ pnpm textor adopt feature path/to/legacy-code my-feat
297
+
290
298
  # Adopt a section by its route
291
299
  pnpm textor adopt /users
292
300
 
@@ -1721,23 +1721,29 @@ function reconstructSections(state, config) {
1721
1721
  // Keep existing sections if their files still exist
1722
1722
  const validSections = (state.sections || []).filter(section => {
1723
1723
  // Check if route file exists in state.files
1724
- const routeFile = Object.keys(files).find(f => {
1724
+ const routeFile = section.route ? Object.keys(files).find(f => {
1725
1725
  const normalizedF = f.replace(/\\/g, '/');
1726
1726
  const routePath = section.route === '/' ? 'index' : section.route.slice(1);
1727
1727
  return normalizedF.startsWith(pagesRoot + '/' + routePath + '.') ||
1728
1728
  normalizedF === pagesRoot + '/' + routePath + '/index.astro'; // nested mode
1729
- });
1729
+ }) : true;
1730
1730
 
1731
1731
  // Check if feature directory has at least one file in state.files
1732
- const hasFeatureFiles = Object.keys(files).some(f =>
1733
- f.replace(/\\/g, '/').startsWith(section.featurePath.replace(/\\/g, '/') + '/')
1734
- );
1732
+ const hasFeatureFiles = section.featurePath ? Object.keys(files).some(f => {
1733
+ const normalizedF = f.replace(/\\/g, '/');
1734
+ const featPath = section.featurePath.replace(/\\/g, '/');
1735
+ return normalizedF.startsWith(featPath + '/') ||
1736
+ normalizedF.startsWith(featuresRoot + '/' + featPath + '/');
1737
+ }) : false;
1735
1738
 
1736
1739
  return routeFile && hasFeatureFiles;
1737
1740
  });
1738
1741
 
1739
1742
  const sections = new Map();
1740
- validSections.forEach(s => sections.set(s.route, s));
1743
+ validSections.forEach(s => {
1744
+ const key = s.route || `feature:${s.featurePath}`;
1745
+ sections.set(key, s);
1746
+ });
1741
1747
 
1742
1748
  // Try to discover new sections
1743
1749
  for (const filePath in files) {
@@ -4313,7 +4319,24 @@ async function syncCommand(options) {
4313
4319
  }
4314
4320
  }
4315
4321
 
4316
- async function adoptCommand(identifier, options) {
4322
+ async function adoptCommand(kind, arg2, arg3, options) {
4323
+ // Handle cases where options is in a different position due to variable arguments
4324
+ if (typeof kind === 'object' && kind !== null && !Array.isArray(kind)) {
4325
+ options = kind;
4326
+ kind = undefined;
4327
+ arg2 = undefined;
4328
+ arg3 = undefined;
4329
+ } else if (typeof arg2 === 'object' && arg2 !== null && !Array.isArray(arg2)) {
4330
+ options = arg2;
4331
+ arg2 = undefined;
4332
+ arg3 = undefined;
4333
+ } else if (typeof arg3 === 'object' && arg3 !== null && !Array.isArray(arg3)) {
4334
+ options = arg3;
4335
+ arg3 = undefined;
4336
+ }
4337
+
4338
+ options = options || {};
4339
+
4317
4340
  try {
4318
4341
  const config = await loadConfig();
4319
4342
  const state = await loadState();
@@ -4325,6 +4348,9 @@ async function adoptCommand(identifier, options) {
4325
4348
  };
4326
4349
 
4327
4350
  let filesToAdopt = [];
4351
+ let identifier = kind;
4352
+ let customName = null;
4353
+ let sourcePath = null;
4328
4354
 
4329
4355
  if (!identifier && options.all) {
4330
4356
  // Adopt all untracked files in all roots
@@ -4335,6 +4361,43 @@ async function adoptCommand(identifier, options) {
4335
4361
  }
4336
4362
  }
4337
4363
  filesToAdopt = Array.from(managedFiles).filter(f => !state.files[f]);
4364
+ } else if (kind === 'component' && arg2) {
4365
+ const componentName = arg2;
4366
+ const untrackedFiles = new Set();
4367
+ const compPath = path.join(roots.components, componentName);
4368
+ if (existsSync(compPath)) {
4369
+ await scanDirectoryOrFile(compPath, untrackedFiles, state);
4370
+ } else {
4371
+ throw new Error(`Component directory not found: ${compPath}`);
4372
+ }
4373
+ filesToAdopt = Array.from(untrackedFiles);
4374
+ } else if (kind === 'feature' && arg2 && arg3) {
4375
+ sourcePath = arg2;
4376
+ customName = arg3;
4377
+ const targetPath = path.join(roots.features, customName);
4378
+ const absoluteSource = path.resolve(process.cwd(), sourcePath);
4379
+ const absoluteTarget = path.resolve(targetPath);
4380
+
4381
+ if (existsSync(absoluteSource)) {
4382
+ if (!options.dryRun && absoluteSource !== absoluteTarget) {
4383
+ if (!existsSync(path.dirname(absoluteTarget))) {
4384
+ await mkdir(path.dirname(absoluteTarget), { recursive: true });
4385
+ }
4386
+ console.log(`Moving files from ${sourcePath} to ${path.relative(process.cwd(), targetPath)}...`);
4387
+ await rename(absoluteSource, absoluteTarget);
4388
+ sourcePath = path.relative(process.cwd(), targetPath);
4389
+ } else if (options.dryRun && absoluteSource !== absoluteTarget) {
4390
+ console.log(`Dry run: would move files from ${sourcePath} to ${path.relative(process.cwd(), targetPath)}`);
4391
+ sourcePath = path.relative(process.cwd(), targetPath);
4392
+ }
4393
+
4394
+ const untrackedFiles = new Set();
4395
+ const fullPath = absoluteSource !== absoluteTarget && !options.dryRun ? absoluteTarget : absoluteSource;
4396
+ await scanDirectoryOrFile(fullPath, untrackedFiles, state);
4397
+ filesToAdopt = Array.from(untrackedFiles);
4398
+ } else {
4399
+ throw new Error(`Source path not found: ${absoluteSource}`);
4400
+ }
4338
4401
  } else if (identifier) {
4339
4402
  const untrackedFiles = new Set();
4340
4403
 
@@ -4888,7 +4951,7 @@ program
4888
4951
  .action(syncCommand);
4889
4952
 
4890
4953
  program
4891
- .command('adopt [path]')
4954
+ .command('adopt [kind] [arg2] [arg3]')
4892
4955
  .description('Adopt untracked files into Textor state, adding signatures')
4893
4956
  .option('--all', 'Adopt all untracked files in managed directories')
4894
4957
  .option('--dry-run', 'Show what would be adopted without applying')
@@ -1 +1 @@
1
- {"version":3,"file":"textor.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"textor.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/index.cjs CHANGED
@@ -1536,18 +1536,26 @@ function reconstructSections(state, config) {
1536
1536
  // Keep existing sections if their files still exist
1537
1537
  const validSections = (state.sections || []).filter(section => {
1538
1538
  // Check if route file exists in state.files
1539
- const routeFile = Object.keys(files).find(f => {
1539
+ const routeFile = section.route ? Object.keys(files).find(f => {
1540
1540
  const normalizedF = f.replace(/\\/g, '/');
1541
1541
  const routePath = section.route === '/' ? 'index' : section.route.slice(1);
1542
1542
  return normalizedF.startsWith(pagesRoot + '/' + routePath + '.') ||
1543
1543
  normalizedF === pagesRoot + '/' + routePath + '/index.astro'; // nested mode
1544
- });
1544
+ }) : true;
1545
1545
  // Check if feature directory has at least one file in state.files
1546
- const hasFeatureFiles = Object.keys(files).some(f => f.replace(/\\/g, '/').startsWith(section.featurePath.replace(/\\/g, '/') + '/'));
1546
+ const hasFeatureFiles = section.featurePath ? Object.keys(files).some(f => {
1547
+ const normalizedF = f.replace(/\\/g, '/');
1548
+ const featPath = section.featurePath.replace(/\\/g, '/');
1549
+ return normalizedF.startsWith(featPath + '/') ||
1550
+ normalizedF.startsWith(featuresRoot + '/' + featPath + '/');
1551
+ }) : false;
1547
1552
  return routeFile && hasFeatureFiles;
1548
1553
  });
1549
1554
  const sections = new Map();
1550
- validSections.forEach(s => sections.set(s.route, s));
1555
+ validSections.forEach(s => {
1556
+ const key = s.route || `feature:${s.featurePath}`;
1557
+ sections.set(key, s);
1558
+ });
1551
1559
  // Try to discover new sections
1552
1560
  for (const filePath in files) {
1553
1561
  const normalizedPath = filePath.replace(/\\/g, '/');
@@ -3638,7 +3646,24 @@ async function syncCommand(options) {
3638
3646
  }
3639
3647
  }
3640
3648
 
3641
- async function adoptCommand(identifier, options) {
3649
+ async function adoptCommand(kind, arg2, arg3, options) {
3650
+ // Handle cases where options is in a different position due to variable arguments
3651
+ if (typeof kind === 'object' && kind !== null && !Array.isArray(kind)) {
3652
+ options = kind;
3653
+ kind = undefined;
3654
+ arg2 = undefined;
3655
+ arg3 = undefined;
3656
+ }
3657
+ else if (typeof arg2 === 'object' && arg2 !== null && !Array.isArray(arg2)) {
3658
+ options = arg2;
3659
+ arg2 = undefined;
3660
+ arg3 = undefined;
3661
+ }
3662
+ else if (typeof arg3 === 'object' && arg3 !== null && !Array.isArray(arg3)) {
3663
+ options = arg3;
3664
+ arg3 = undefined;
3665
+ }
3666
+ options = options || {};
3642
3667
  try {
3643
3668
  const config = await loadConfig();
3644
3669
  const state = await loadState();
@@ -3648,6 +3673,9 @@ async function adoptCommand(identifier, options) {
3648
3673
  components: resolvePath(config, 'components')
3649
3674
  };
3650
3675
  let filesToAdopt = [];
3676
+ let identifier = kind;
3677
+ let customName = null;
3678
+ let sourcePath = null;
3651
3679
  if (!identifier && options.all) {
3652
3680
  // Adopt all untracked files in all roots
3653
3681
  const managedFiles = new Set();
@@ -3658,6 +3686,46 @@ async function adoptCommand(identifier, options) {
3658
3686
  }
3659
3687
  filesToAdopt = Array.from(managedFiles).filter(f => !state.files[f]);
3660
3688
  }
3689
+ else if (kind === 'component' && arg2) {
3690
+ const componentName = arg2;
3691
+ const untrackedFiles = new Set();
3692
+ const compPath = path.join(roots.components, componentName);
3693
+ if (fs.existsSync(compPath)) {
3694
+ await scanDirectoryOrFile(compPath, untrackedFiles, state);
3695
+ }
3696
+ else {
3697
+ throw new Error(`Component directory not found: ${compPath}`);
3698
+ }
3699
+ filesToAdopt = Array.from(untrackedFiles);
3700
+ }
3701
+ else if (kind === 'feature' && arg2 && arg3) {
3702
+ sourcePath = arg2;
3703
+ customName = arg3;
3704
+ const targetPath = path.join(roots.features, customName);
3705
+ const absoluteSource = path.resolve(process.cwd(), sourcePath);
3706
+ const absoluteTarget = path.resolve(targetPath);
3707
+ if (fs.existsSync(absoluteSource)) {
3708
+ if (!options.dryRun && absoluteSource !== absoluteTarget) {
3709
+ if (!fs.existsSync(path.dirname(absoluteTarget))) {
3710
+ await promises.mkdir(path.dirname(absoluteTarget), { recursive: true });
3711
+ }
3712
+ console.log(`Moving files from ${sourcePath} to ${path.relative(process.cwd(), targetPath)}...`);
3713
+ await promises.rename(absoluteSource, absoluteTarget);
3714
+ sourcePath = path.relative(process.cwd(), targetPath);
3715
+ }
3716
+ else if (options.dryRun && absoluteSource !== absoluteTarget) {
3717
+ console.log(`Dry run: would move files from ${sourcePath} to ${path.relative(process.cwd(), targetPath)}`);
3718
+ sourcePath = path.relative(process.cwd(), targetPath);
3719
+ }
3720
+ const untrackedFiles = new Set();
3721
+ const fullPath = absoluteSource !== absoluteTarget && !options.dryRun ? absoluteTarget : absoluteSource;
3722
+ await scanDirectoryOrFile(fullPath, untrackedFiles, state);
3723
+ filesToAdopt = Array.from(untrackedFiles);
3724
+ }
3725
+ else {
3726
+ throw new Error(`Source path not found: ${absoluteSource}`);
3727
+ }
3728
+ }
3661
3729
  else if (identifier) {
3662
3730
  const untrackedFiles = new Set();
3663
3731
  // 1. Try as direct path