@oamm/textor 1.0.3 → 1.0.4

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
@@ -269,6 +269,16 @@ pnpm textor upgrade-config
269
269
  **Options:**
270
270
  - `--dry-run`: Print the upgraded config without writing it.
271
271
 
272
+ ### normalize-state
273
+ Normalize `.textor/state.json` to use project-relative paths (helpful when moving between machines).
274
+
275
+ ```bash
276
+ pnpm textor normalize-state
277
+ ```
278
+
279
+ **Options:**
280
+ - `--dry-run`: Print the normalized state without writing it.
281
+
272
282
  ## 🏗️ Technical Architecture
273
283
 
274
284
  Textor is designed with enterprise-grade robustness, moving beyond simple scaffolding to provide a reliable refactoring engine.
@@ -1458,6 +1458,7 @@ async function loadState() {
1458
1458
  const content = await readFile(statePath, 'utf-8');
1459
1459
  const state = JSON.parse(content);
1460
1460
  if (!state.files) state.files = {};
1461
+ normalizeStatePaths(state);
1461
1462
  return state;
1462
1463
  } catch (error) {
1463
1464
  return { sections: [], components: [], files: {} };
@@ -1507,24 +1508,62 @@ async function registerFile(filePath, { kind, template, hash, templateVersion =
1507
1508
 
1508
1509
  async function addSectionToState(section) {
1509
1510
  const state = await loadState();
1511
+ const normalizedSection = { ...section };
1512
+ if (normalizedSection.featurePath) {
1513
+ normalizedSection.featurePath = normalizeStatePath(normalizedSection.featurePath);
1514
+ }
1510
1515
  // Avoid duplicates by route OR by featurePath if route is null
1511
- if (section.route) {
1512
- state.sections = state.sections.filter(s => s.route !== section.route);
1516
+ if (normalizedSection.route) {
1517
+ state.sections = state.sections.filter(s => s.route !== normalizedSection.route);
1513
1518
  } else {
1514
- state.sections = state.sections.filter(s => s.featurePath !== section.featurePath || s.route);
1519
+ state.sections = state.sections.filter(s => s.featurePath !== normalizedSection.featurePath || s.route);
1515
1520
  }
1516
- state.sections.push(section);
1521
+ state.sections.push(normalizedSection);
1517
1522
  await saveState(state);
1518
1523
  }
1519
1524
 
1520
1525
  async function addComponentToState(component) {
1521
1526
  const state = await loadState();
1527
+ const normalizedComponent = { ...component };
1528
+ if (normalizedComponent.path) {
1529
+ normalizedComponent.path = normalizeStatePath(normalizedComponent.path);
1530
+ }
1522
1531
  // Avoid duplicates by name
1523
- state.components = state.components.filter(c => c.name !== component.name);
1524
- state.components.push(component);
1532
+ state.components = state.components.filter(c => c.name !== normalizedComponent.name);
1533
+ state.components.push(normalizedComponent);
1525
1534
  await saveState(state);
1526
1535
  }
1527
1536
 
1537
+ function normalizeStatePath(filePath) {
1538
+ if (!filePath || typeof filePath !== 'string') return filePath;
1539
+ const relative = path.isAbsolute(filePath)
1540
+ ? path.relative(process.cwd(), filePath)
1541
+ : filePath;
1542
+ return relative.replace(/\\/g, '/');
1543
+ }
1544
+
1545
+ function normalizeStatePaths(state) {
1546
+ if (!state || typeof state !== 'object') return;
1547
+ if (Array.isArray(state.sections)) {
1548
+ state.sections = state.sections.map(section => {
1549
+ if (!section || typeof section !== 'object') return section;
1550
+ if (!section.featurePath) return section;
1551
+ const normalized = normalizeStatePath(section.featurePath);
1552
+ if (normalized === section.featurePath) return section;
1553
+ return { ...section, featurePath: normalized };
1554
+ });
1555
+ }
1556
+ if (Array.isArray(state.components)) {
1557
+ state.components = state.components.map(component => {
1558
+ if (!component || typeof component !== 'object') return component;
1559
+ if (!component.path) return component;
1560
+ const normalized = normalizeStatePath(component.path);
1561
+ if (normalized === component.path) return component;
1562
+ return { ...component, path: normalized };
1563
+ });
1564
+ }
1565
+ }
1566
+
1528
1567
  function findSection(state, identifier) {
1529
1568
  return state.sections.find(s => s.route === identifier || s.name === identifier || s.featurePath === identifier);
1530
1569
  }
@@ -3298,7 +3337,7 @@ async function removeComponentCommand(identifier, options) {
3298
3337
  let componentDir;
3299
3338
 
3300
3339
  if (component) {
3301
- componentDir = component.path;
3340
+ componentDir = path.resolve(process.cwd(), component.path);
3302
3341
  } else {
3303
3342
  // Fallback: try to guess path if not in state
3304
3343
  const componentsRoot = path.resolve(process.cwd(), config.paths.components);
@@ -4032,6 +4071,27 @@ async function upgradeConfigCommand(options) {
4032
4071
  }
4033
4072
  }
4034
4073
 
4074
+ async function normalizeStateCommand(options) {
4075
+ try {
4076
+ const state = await loadState();
4077
+
4078
+ if (options.dryRun) {
4079
+ console.log('Dry run - normalized state:');
4080
+ console.log(JSON.stringify(state, null, 2));
4081
+ return;
4082
+ }
4083
+
4084
+ await saveState(state);
4085
+ console.log('State normalized successfully.');
4086
+ } catch (error) {
4087
+ console.error('Error:', error.message);
4088
+ if (typeof process.exit === 'function' && process.env.NODE_ENV !== 'test') {
4089
+ process.exit(1);
4090
+ }
4091
+ throw error;
4092
+ }
4093
+ }
4094
+
4035
4095
  const program = new Command();
4036
4096
 
4037
4097
  program
@@ -4157,5 +4217,11 @@ program
4157
4217
  .option('--dry-run', 'Show the upgraded config without writing to disk')
4158
4218
  .action(upgradeConfigCommand);
4159
4219
 
4220
+ program
4221
+ .command('normalize-state')
4222
+ .description('Normalize state paths to be project-relative')
4223
+ .option('--dry-run', 'Show the normalized state without writing to disk')
4224
+ .action(normalizeStateCommand);
4225
+
4160
4226
  program.parse();
4161
4227
  //# sourceMappingURL=textor.js.map
@@ -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
@@ -1291,6 +1291,7 @@ async function loadState() {
1291
1291
  const state = JSON.parse(content);
1292
1292
  if (!state.files)
1293
1293
  state.files = {};
1294
+ normalizeStatePaths(state);
1294
1295
  return state;
1295
1296
  }
1296
1297
  catch (error) {
@@ -1331,23 +1332,67 @@ async function registerFile(filePath, { kind, template, hash, templateVersion =
1331
1332
  }
1332
1333
  async function addSectionToState(section) {
1333
1334
  const state = await loadState();
1335
+ const normalizedSection = { ...section };
1336
+ if (normalizedSection.featurePath) {
1337
+ normalizedSection.featurePath = normalizeStatePath(normalizedSection.featurePath);
1338
+ }
1334
1339
  // Avoid duplicates by route OR by featurePath if route is null
1335
- if (section.route) {
1336
- state.sections = state.sections.filter(s => s.route !== section.route);
1340
+ if (normalizedSection.route) {
1341
+ state.sections = state.sections.filter(s => s.route !== normalizedSection.route);
1337
1342
  }
1338
1343
  else {
1339
- state.sections = state.sections.filter(s => s.featurePath !== section.featurePath || s.route);
1344
+ state.sections = state.sections.filter(s => s.featurePath !== normalizedSection.featurePath || s.route);
1340
1345
  }
1341
- state.sections.push(section);
1346
+ state.sections.push(normalizedSection);
1342
1347
  await saveState(state);
1343
1348
  }
1344
1349
  async function addComponentToState(component) {
1345
1350
  const state = await loadState();
1351
+ const normalizedComponent = { ...component };
1352
+ if (normalizedComponent.path) {
1353
+ normalizedComponent.path = normalizeStatePath(normalizedComponent.path);
1354
+ }
1346
1355
  // Avoid duplicates by name
1347
- state.components = state.components.filter(c => c.name !== component.name);
1348
- state.components.push(component);
1356
+ state.components = state.components.filter(c => c.name !== normalizedComponent.name);
1357
+ state.components.push(normalizedComponent);
1349
1358
  await saveState(state);
1350
1359
  }
1360
+ function normalizeStatePath(filePath) {
1361
+ if (!filePath || typeof filePath !== 'string')
1362
+ return filePath;
1363
+ const relative = path.isAbsolute(filePath)
1364
+ ? path.relative(process.cwd(), filePath)
1365
+ : filePath;
1366
+ return relative.replace(/\\/g, '/');
1367
+ }
1368
+ function normalizeStatePaths(state) {
1369
+ if (!state || typeof state !== 'object')
1370
+ return;
1371
+ if (Array.isArray(state.sections)) {
1372
+ state.sections = state.sections.map(section => {
1373
+ if (!section || typeof section !== 'object')
1374
+ return section;
1375
+ if (!section.featurePath)
1376
+ return section;
1377
+ const normalized = normalizeStatePath(section.featurePath);
1378
+ if (normalized === section.featurePath)
1379
+ return section;
1380
+ return { ...section, featurePath: normalized };
1381
+ });
1382
+ }
1383
+ if (Array.isArray(state.components)) {
1384
+ state.components = state.components.map(component => {
1385
+ if (!component || typeof component !== 'object')
1386
+ return component;
1387
+ if (!component.path)
1388
+ return component;
1389
+ const normalized = normalizeStatePath(component.path);
1390
+ if (normalized === component.path)
1391
+ return component;
1392
+ return { ...component, path: normalized };
1393
+ });
1394
+ }
1395
+ }
1351
1396
  function findSection(state, identifier) {
1352
1397
  return state.sections.find(s => s.route === identifier || s.name === identifier || s.featurePath === identifier);
1353
1398
  }
@@ -2712,7 +2757,7 @@ async function removeComponentCommand(identifier, options) {
2712
2757
  const component = findComponent(state, identifier);
2713
2758
  let componentDir;
2714
2759
  if (component) {
2715
- componentDir = component.path;
2760
+ componentDir = path.resolve(process.cwd(), component.path);
2716
2761
  }
2717
2762
  else {
2718
2763
  // Fallback: try to guess path if not in state
@@ -3376,12 +3421,33 @@ async function upgradeConfigCommand(options) {
3376
3421
  }
3377
3422
  }
3378
3423
 
3424
+ async function normalizeStateCommand(options) {
3425
+ try {
3426
+ const state = await loadState();
3427
+ if (options.dryRun) {
3428
+ console.log('Dry run - normalized state:');
3429
+ console.log(JSON.stringify(state, null, 2));
3430
+ return;
3431
+ }
3432
+ await saveState(state);
3433
+ console.log('State normalized successfully.');
3434
+ }
3435
+ catch (error) {
3436
+ console.error('Error:', error.message);
3437
+ if (typeof process.exit === 'function' && process.env.NODE_ENV !== 'test') {
3438
+ process.exit(1);
3439
+ }
3440
+ throw error;
3441
+ }
3442
+ }
3443
+
3379
3444
  exports.addSectionCommand = addSectionCommand;
3380
3445
  exports.adoptCommand = adoptCommand;
3381
3446
  exports.createComponentCommand = createComponentCommand;
3382
3447
  exports.initCommand = initCommand;
3383
3448
  exports.listSectionsCommand = listSectionsCommand;
3384
3449
  exports.moveSectionCommand = moveSectionCommand;
3450
+ exports.normalizeStateCommand = normalizeStateCommand;
3385
3451
  exports.removeComponentCommand = removeComponentCommand;
3386
3452
  exports.removeSectionCommand = removeSectionCommand;
3387
3453
  exports.statusCommand = statusCommand;