@oamm/textor 1.0.5 → 1.0.7

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
@@ -370,7 +370,8 @@ The .textor/config.json file allows full control over the tool's behavior.
370
370
  "createTypes": false,
371
371
  "createReadme": false,
372
372
  "createStories": false,
373
- "createIndex": false
373
+ "createIndex": false,
374
+ "layout": "Main"
374
375
  },
375
376
  "components": {
376
377
  "framework": "react",
@@ -36,10 +36,12 @@ const CURRENT_CONFIG_VERSION = 2;
36
36
  * @property {string} signatures.typescript
37
37
  * @property {string} signatures.javascript
38
38
  * @property {Object} features
39
+ * @property {string} features.framework
39
40
  * @property {string} features.entry
40
41
  * @property {boolean} features.createSubComponentsDir
41
42
  * @property {boolean} features.createScriptsDir
42
43
  * @property {string} features.scriptsIndexFile
44
+ * @property {string} features.layout
43
45
  * @property {Object} components
44
46
  * @property {boolean} components.createSubComponentsDir
45
47
  * @property {boolean} components.createContext
@@ -105,7 +107,8 @@ const DEFAULT_CONFIG = {
105
107
  createTypes: false,
106
108
  createReadme: false,
107
109
  createStories: false,
108
- createIndex: false
110
+ createIndex: false,
111
+ layout: 'Main'
109
112
  },
110
113
  components: {
111
114
  framework: 'react',
@@ -1794,6 +1797,7 @@ async function addSectionCommand(route, featurePath, options) {
1794
1797
 
1795
1798
  const {
1796
1799
  framework,
1800
+ layout,
1797
1801
  createSubComponentsDir: shouldCreateSubComponentsDir,
1798
1802
  createScriptsDir: shouldCreateScriptsDir,
1799
1803
  createApi: shouldCreateApi,
@@ -1965,7 +1969,13 @@ async function addSectionCommand(route, featurePath, options) {
1965
1969
  }
1966
1970
 
1967
1971
  // Update imports in the moved file
1968
- await updateImportsInFile(reorg.to, reorg.from, reorg.to);
1972
+ await updateImportsInFile$1(reorg.to, reorg.from, reorg.to);
1973
+
1974
+ // Update hash in state after import updates
1975
+ if (state.files[newRelative]) {
1976
+ const content = await readFile(reorg.to, 'utf-8');
1977
+ state.files[newRelative].hash = calculateHash(content, config.hashing?.normalization);
1978
+ }
1969
1979
 
1970
1980
  console.log(`✓ Reorganized ${oldRelative} to ${newRelative}`);
1971
1981
  }
@@ -1988,11 +1998,11 @@ async function addSectionCommand(route, featurePath, options) {
1988
1998
  if (shouldCreateScriptsDir) await ensureNotExists(scriptsIndexPath, options.force);
1989
1999
 
1990
2000
  let layoutImportPath = null;
1991
- if (routeFilePath && options.layout !== 'none') {
2001
+ if (routeFilePath && layout !== 'none') {
1992
2002
  if (config.importAliases.layouts) {
1993
- layoutImportPath = `${config.importAliases.layouts}/${options.layout}.astro`;
2003
+ layoutImportPath = `${config.importAliases.layouts}/${layout}.astro`;
1994
2004
  } else {
1995
- const layoutFilePath = secureJoin(layoutsRoot, `${options.layout}.astro`);
2005
+ const layoutFilePath = secureJoin(layoutsRoot, `${layout}.astro`);
1996
2006
  layoutImportPath = getRelativeImportPath(routeFilePath, layoutFilePath);
1997
2007
  }
1998
2008
  }
@@ -2029,7 +2039,7 @@ async function addSectionCommand(route, featurePath, options) {
2029
2039
  routeSignature = getSignature(config, 'typescript');
2030
2040
  } else {
2031
2041
  routeContent = generateRouteTemplate(
2032
- options.layout,
2042
+ layout,
2033
2043
  layoutImportPath,
2034
2044
  featureImportPath,
2035
2045
  featureComponentName,
@@ -2301,7 +2311,7 @@ async function addSectionCommand(route, featurePath, options) {
2301
2311
  name: options.name || featureComponentName,
2302
2312
  route: normalizedRoute,
2303
2313
  featurePath: normalizedFeaturePath,
2304
- layout: options.layout,
2314
+ layout: layout,
2305
2315
  extension: routeExtension
2306
2316
  });
2307
2317
 
@@ -2318,7 +2328,7 @@ async function addSectionCommand(route, featurePath, options) {
2318
2328
  }
2319
2329
  }
2320
2330
 
2321
- async function updateImportsInFile(filePath, oldFilePath, newFilePath) {
2331
+ async function updateImportsInFile$1(filePath, oldFilePath, newFilePath) {
2322
2332
  if (!existsSync(filePath)) return;
2323
2333
 
2324
2334
  let content = await readFile(filePath, 'utf-8');
@@ -2361,33 +2371,43 @@ async function removeSectionCommand(route, featurePath, options) {
2361
2371
 
2362
2372
  const state = await loadState();
2363
2373
 
2364
- let targetRoute = route;
2365
- let targetFeaturePath = featurePath;
2366
2374
  let section = findSection(state, route);
2375
+ if (!section && featurePath) {
2376
+ section = findSection(state, featurePath);
2377
+ }
2378
+
2379
+ const targetRoute = section ? section.route : route;
2380
+ const targetFeaturePath = section ? section.featurePath : featurePath;
2367
2381
 
2368
2382
  if (!targetFeaturePath) {
2369
- if (section) {
2370
- targetRoute = section.route;
2371
- targetFeaturePath = section.featurePath;
2372
- } else {
2373
- throw new Error(`Section not found for identifier: ${route}. Please provide both route and featurePath.`);
2374
- }
2383
+ throw new Error(`Section not found for identifier: ${route}. Please provide both route and featurePath.`);
2375
2384
  }
2376
2385
 
2377
2386
  const normalizedRoute = normalizeRoute(targetRoute);
2378
2387
  const normalizedFeaturePath = featureToDirectoryPath(targetFeaturePath);
2379
2388
 
2380
- const routeExtension = (section && section.extension) || config.naming.routeExtension;
2381
- const routeFileName = routeToFilePath(normalizedRoute, {
2382
- extension: routeExtension,
2383
- mode: config.routing.mode,
2384
- indexFile: config.routing.indexFile
2385
- });
2386
-
2387
2389
  const pagesRoot = resolvePath(config, 'pages');
2388
2390
  const featuresRoot = resolvePath(config, 'features');
2391
+
2392
+ // Find route file in state if possible
2393
+ let routeFilePath = null;
2394
+ const routeRelPath = Object.keys(state.files).find(f => {
2395
+ const data = state.files[f];
2396
+ return data.kind === 'route' && data.owner === normalizedRoute;
2397
+ });
2398
+
2399
+ if (routeRelPath) {
2400
+ routeFilePath = path.resolve(process.cwd(), routeRelPath);
2401
+ } else {
2402
+ const routeExtension = (section && section.extension) || config.naming.routeExtension;
2403
+ const routeFileName = routeToFilePath(normalizedRoute, {
2404
+ extension: routeExtension,
2405
+ mode: config.routing.mode,
2406
+ indexFile: config.routing.indexFile
2407
+ });
2408
+ routeFilePath = secureJoin(pagesRoot, routeFileName);
2409
+ }
2389
2410
 
2390
- const routeFilePath = secureJoin(pagesRoot, routeFileName);
2391
2411
  const featureDirPath = secureJoin(featuresRoot, normalizedFeaturePath);
2392
2412
 
2393
2413
  const deletedFiles = [];
@@ -2474,8 +2494,67 @@ async function removeSectionCommand(route, featurePath, options) {
2474
2494
  }
2475
2495
 
2476
2496
  if (deletedFiles.length === 0 && deletedDirs.length === 0 && skippedFiles.length === 0) {
2477
- console.log('No files to delete.');
2497
+ if (section) {
2498
+ console.log(`✓ Section ${normalizedRoute} removed from state (files were already missing on disk).`);
2499
+ state.sections = state.sections.filter(s => s.route !== normalizedRoute);
2500
+ await saveState(state);
2501
+ } else {
2502
+ console.log('No files to delete.');
2503
+ }
2478
2504
  } else {
2505
+ // Reorganization (Flattening)
2506
+ if (!options.keepRoute && deletedFiles.length > 0 && config.routing.mode === 'flat') {
2507
+ const routeParts = normalizedRoute.split('/').filter(Boolean);
2508
+ if (routeParts.length > 1) {
2509
+ for (let i = routeParts.length - 1; i >= 1; i--) {
2510
+ const parentRoute = '/' + routeParts.slice(0, i).join('/');
2511
+ const parentDirName = routeParts.slice(0, i).join('/');
2512
+ const parentDirPath = secureJoin(pagesRoot, parentDirName);
2513
+
2514
+ if (existsSync(parentDirPath)) {
2515
+ const filesInDir = await readdir(parentDirPath);
2516
+
2517
+ if (filesInDir.length === 1) {
2518
+ const loneFile = filesInDir[0];
2519
+ const ext = path.extname(loneFile);
2520
+ const indexFile = ext === '.astro' ? config.routing.indexFile : `index${ext}`;
2521
+
2522
+ if (loneFile === indexFile) {
2523
+ const loneFilePath = path.join(parentDirPath, loneFile);
2524
+ const oldRelative = path.relative(process.cwd(), loneFilePath).replace(/\\/g, '/');
2525
+
2526
+ if (state.files[oldRelative] && state.files[oldRelative].kind === 'route') {
2527
+ const flatFileName = routeToFilePath(parentRoute, {
2528
+ extension: ext,
2529
+ mode: 'flat'
2530
+ });
2531
+ const flatFilePath = secureJoin(pagesRoot, flatFileName);
2532
+
2533
+ if (!existsSync(flatFilePath)) {
2534
+ await rename(loneFilePath, flatFilePath);
2535
+
2536
+ const newRelative = path.relative(process.cwd(), flatFilePath).replace(/\\/g, '/');
2537
+
2538
+ state.files[newRelative] = { ...state.files[oldRelative] };
2539
+ delete state.files[oldRelative];
2540
+
2541
+ await updateImportsInFile(flatFilePath, loneFilePath, flatFilePath);
2542
+
2543
+ // Update hash in state after import updates
2544
+ const content = await readFile(flatFilePath, 'utf-8');
2545
+ state.files[newRelative].hash = calculateHash(content, config.hashing?.normalization);
2546
+
2547
+ console.log(`✓ Reorganized ${oldRelative} to ${newRelative} (flattened)`);
2548
+ await cleanupEmptyDirs(parentDirPath, pagesRoot);
2549
+ }
2550
+ }
2551
+ }
2552
+ }
2553
+ }
2554
+ }
2555
+ }
2556
+ }
2557
+
2479
2558
  state.sections = state.sections.filter(s => s.route !== normalizedRoute);
2480
2559
  await saveState(state);
2481
2560
  }
@@ -2489,6 +2568,39 @@ async function removeSectionCommand(route, featurePath, options) {
2489
2568
  }
2490
2569
  }
2491
2570
 
2571
+ async function updateImportsInFile(filePath, oldFilePath, newFilePath) {
2572
+ if (!existsSync(filePath)) return;
2573
+
2574
+ let content = await readFile(filePath, 'utf-8');
2575
+ const oldDir = path.dirname(oldFilePath);
2576
+ const newDir = path.dirname(newFilePath);
2577
+
2578
+ if (oldDir === newDir) return;
2579
+
2580
+ // Find all relative imports
2581
+ const relativeImportRegex = /from\s+['"](\.\.?\/[^'"]+)['"]/g;
2582
+ let match;
2583
+ const replacements = [];
2584
+
2585
+ while ((match = relativeImportRegex.exec(content)) !== null) {
2586
+ const relativePath = match[1];
2587
+ const absoluteTarget = path.resolve(oldDir, relativePath);
2588
+ const newRelativePath = getRelativeImportPath(newFilePath, absoluteTarget);
2589
+
2590
+ replacements.push({
2591
+ full: match[0],
2592
+ oldRel: relativePath,
2593
+ newRel: newRelativePath
2594
+ });
2595
+ }
2596
+
2597
+ for (const repl of replacements) {
2598
+ content = content.replace(repl.full, `from '${repl.newRel}'`);
2599
+ }
2600
+
2601
+ await writeFile(filePath, content, 'utf-8');
2602
+ }
2603
+
2492
2604
  /**
2493
2605
  * Move a section (route + feature).
2494
2606
  *
@@ -3402,9 +3514,13 @@ async function removeComponentCommand(identifier, options) {
3402
3514
  owner: identifier
3403
3515
  });
3404
3516
 
3405
- if (result.deleted) {
3406
- console.log(`✓ Deleted component: ${componentDir}/`);
3407
- await cleanupEmptyDirs(path.dirname(componentDir), path.join(process.cwd(), config.paths.components));
3517
+ if (result.deleted || (result.reason === 'not-found' && component)) {
3518
+ if (result.deleted) {
3519
+ console.log(`✓ Deleted component: ${componentDir}/`);
3520
+ await cleanupEmptyDirs(path.dirname(componentDir), path.join(process.cwd(), config.paths.components));
3521
+ } else {
3522
+ console.log(`✓ Component ${identifier} removed from state (directory was already missing on disk).`);
3523
+ }
3408
3524
 
3409
3525
  // Unregister files
3410
3526
  const relComponentPath = path.relative(process.cwd(), componentDir).replace(/\\/g, '/');
@@ -4155,7 +4271,7 @@ program
4155
4271
  .command('add-section [route] [featurePath]')
4156
4272
  .description('Create a route + feature binding (route optional for standalone features)')
4157
4273
  .option('--preset <name>', 'Scaffolding preset (minimal, standard, senior)')
4158
- .option('--layout <name>', 'Layout component name (use "none" for no layout)', 'Main')
4274
+ .option('--layout <name>', 'Layout component name (use "none" for no layout)')
4159
4275
  .option('--name <name>', 'Section name for state tracking')
4160
4276
  .option('--endpoint', 'Create an API endpoint (.ts) instead of an Astro page')
4161
4277
  .option('--api', 'Create api directory')
@@ -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
@@ -35,10 +35,12 @@ const CURRENT_CONFIG_VERSION = 2;
35
35
  * @property {string} signatures.typescript
36
36
  * @property {string} signatures.javascript
37
37
  * @property {Object} features
38
+ * @property {string} features.framework
38
39
  * @property {string} features.entry
39
40
  * @property {boolean} features.createSubComponentsDir
40
41
  * @property {boolean} features.createScriptsDir
41
42
  * @property {string} features.scriptsIndexFile
43
+ * @property {string} features.layout
42
44
  * @property {Object} components
43
45
  * @property {boolean} components.createSubComponentsDir
44
46
  * @property {boolean} components.createContext
@@ -103,7 +105,8 @@ const DEFAULT_CONFIG = {
103
105
  createTypes: false,
104
106
  createReadme: false,
105
107
  createStories: false,
106
- createIndex: false
108
+ createIndex: false,
109
+ layout: 'Main'
107
110
  },
108
111
  components: {
109
112
  framework: 'react',
@@ -1590,7 +1593,7 @@ async function addSectionCommand(route, featurePath, options) {
1590
1593
  const apiDirInside = secureJoin(featureDirPath, 'api');
1591
1594
  const servicesDirInside = secureJoin(featureDirPath, 'services');
1592
1595
  const schemasDirInside = secureJoin(featureDirPath, 'schemas');
1593
- const { framework, createSubComponentsDir: shouldCreateSubComponentsDir, createScriptsDir: shouldCreateScriptsDir, createApi: shouldCreateApi, createServices: shouldCreateServices, createSchemas: shouldCreateSchemas, createHooks: shouldCreateHooks, createContext: shouldCreateContext, createTests: shouldCreateTests, createTypes: shouldCreateTypes, createReadme: shouldCreateReadme, createStories: shouldCreateStories, createIndex: shouldCreateIndex } = effectiveOptions;
1596
+ const { framework, layout, createSubComponentsDir: shouldCreateSubComponentsDir, createScriptsDir: shouldCreateScriptsDir, createApi: shouldCreateApi, createServices: shouldCreateServices, createSchemas: shouldCreateSchemas, createHooks: shouldCreateHooks, createContext: shouldCreateContext, createTests: shouldCreateTests, createTypes: shouldCreateTypes, createReadme: shouldCreateReadme, createStories: shouldCreateStories, createIndex: shouldCreateIndex } = effectiveOptions;
1594
1597
  const featurePatterns = config.filePatterns?.features || {};
1595
1598
  const patternData = {
1596
1599
  componentName: featureComponentName,
@@ -1687,7 +1690,12 @@ async function addSectionCommand(route, featurePath, options) {
1687
1690
  delete state.files[oldRelative];
1688
1691
  }
1689
1692
  // Update imports in the moved file
1690
- await updateImportsInFile(reorg.to, reorg.from, reorg.to);
1693
+ await updateImportsInFile$1(reorg.to, reorg.from, reorg.to);
1694
+ // Update hash in state after import updates
1695
+ if (state.files[newRelative]) {
1696
+ const content = await promises.readFile(reorg.to, 'utf-8');
1697
+ state.files[newRelative].hash = calculateHash(content, config.hashing?.normalization);
1698
+ }
1691
1699
  console.log(`✓ Reorganized ${oldRelative} to ${newRelative}`);
1692
1700
  }
1693
1701
  await saveState(state);
@@ -1718,12 +1726,12 @@ async function addSectionCommand(route, featurePath, options) {
1718
1726
  if (shouldCreateScriptsDir)
1719
1727
  await ensureNotExists(scriptsIndexPath, options.force);
1720
1728
  let layoutImportPath = null;
1721
- if (routeFilePath && options.layout !== 'none') {
1729
+ if (routeFilePath && layout !== 'none') {
1722
1730
  if (config.importAliases.layouts) {
1723
- layoutImportPath = `${config.importAliases.layouts}/${options.layout}.astro`;
1731
+ layoutImportPath = `${config.importAliases.layouts}/${layout}.astro`;
1724
1732
  }
1725
1733
  else {
1726
- const layoutFilePath = secureJoin(layoutsRoot, `${options.layout}.astro`);
1734
+ const layoutFilePath = secureJoin(layoutsRoot, `${layout}.astro`);
1727
1735
  layoutImportPath = getRelativeImportPath(routeFilePath, layoutFilePath);
1728
1736
  }
1729
1737
  }
@@ -1758,7 +1766,7 @@ async function addSectionCommand(route, featurePath, options) {
1758
1766
  routeSignature = getSignature(config, 'typescript');
1759
1767
  }
1760
1768
  else {
1761
- routeContent = generateRouteTemplate(options.layout, layoutImportPath, featureImportPath, featureComponentName, routeExtension);
1769
+ routeContent = generateRouteTemplate(layout, layoutImportPath, featureImportPath, featureComponentName, routeExtension);
1762
1770
  routeSignature = getSignature(config, 'astro');
1763
1771
  }
1764
1772
  }
@@ -1959,7 +1967,7 @@ async function addSectionCommand(route, featurePath, options) {
1959
1967
  name: options.name || featureComponentName,
1960
1968
  route: normalizedRoute,
1961
1969
  featurePath: normalizedFeaturePath,
1962
- layout: options.layout,
1970
+ layout: layout,
1963
1971
  extension: routeExtension
1964
1972
  });
1965
1973
  if (config.git?.stageChanges) {
@@ -1974,7 +1982,7 @@ async function addSectionCommand(route, featurePath, options) {
1974
1982
  throw error;
1975
1983
  }
1976
1984
  }
1977
- async function updateImportsInFile(filePath, oldFilePath, newFilePath) {
1985
+ async function updateImportsInFile$1(filePath, oldFilePath, newFilePath) {
1978
1986
  if (!fs.existsSync(filePath))
1979
1987
  return;
1980
1988
  let content = await promises.readFile(filePath, 'utf-8');
@@ -2009,29 +2017,37 @@ async function removeSectionCommand(route, featurePath, options) {
2009
2017
  throw new Error('Git repository is not clean. Please commit or stash your changes before proceeding.');
2010
2018
  }
2011
2019
  const state = await loadState();
2012
- let targetRoute = route;
2013
- let targetFeaturePath = featurePath;
2014
2020
  let section = findSection(state, route);
2021
+ if (!section && featurePath) {
2022
+ section = findSection(state, featurePath);
2023
+ }
2024
+ const targetRoute = section ? section.route : route;
2025
+ const targetFeaturePath = section ? section.featurePath : featurePath;
2015
2026
  if (!targetFeaturePath) {
2016
- if (section) {
2017
- targetRoute = section.route;
2018
- targetFeaturePath = section.featurePath;
2019
- }
2020
- else {
2021
- throw new Error(`Section not found for identifier: ${route}. Please provide both route and featurePath.`);
2022
- }
2027
+ throw new Error(`Section not found for identifier: ${route}. Please provide both route and featurePath.`);
2023
2028
  }
2024
2029
  const normalizedRoute = normalizeRoute(targetRoute);
2025
2030
  const normalizedFeaturePath = featureToDirectoryPath(targetFeaturePath);
2026
- const routeExtension = (section && section.extension) || config.naming.routeExtension;
2027
- const routeFileName = routeToFilePath(normalizedRoute, {
2028
- extension: routeExtension,
2029
- mode: config.routing.mode,
2030
- indexFile: config.routing.indexFile
2031
- });
2032
2031
  const pagesRoot = resolvePath(config, 'pages');
2033
2032
  const featuresRoot = resolvePath(config, 'features');
2034
- const routeFilePath = secureJoin(pagesRoot, routeFileName);
2033
+ // Find route file in state if possible
2034
+ let routeFilePath = null;
2035
+ const routeRelPath = Object.keys(state.files).find(f => {
2036
+ const data = state.files[f];
2037
+ return data.kind === 'route' && data.owner === normalizedRoute;
2038
+ });
2039
+ if (routeRelPath) {
2040
+ routeFilePath = path.resolve(process.cwd(), routeRelPath);
2041
+ }
2042
+ else {
2043
+ const routeExtension = (section && section.extension) || config.naming.routeExtension;
2044
+ const routeFileName = routeToFilePath(normalizedRoute, {
2045
+ extension: routeExtension,
2046
+ mode: config.routing.mode,
2047
+ indexFile: config.routing.indexFile
2048
+ });
2049
+ routeFilePath = secureJoin(pagesRoot, routeFileName);
2050
+ }
2035
2051
  const featureDirPath = secureJoin(featuresRoot, normalizedFeaturePath);
2036
2052
  const deletedFiles = [];
2037
2053
  const skippedFiles = [];
@@ -2106,9 +2122,58 @@ async function removeSectionCommand(route, featurePath, options) {
2106
2122
  });
2107
2123
  }
2108
2124
  if (deletedFiles.length === 0 && deletedDirs.length === 0 && skippedFiles.length === 0) {
2109
- console.log('No files to delete.');
2125
+ if (section) {
2126
+ console.log(`✓ Section ${normalizedRoute} removed from state (files were already missing on disk).`);
2127
+ state.sections = state.sections.filter(s => s.route !== normalizedRoute);
2128
+ await saveState(state);
2129
+ }
2130
+ else {
2131
+ console.log('No files to delete.');
2132
+ }
2110
2133
  }
2111
2134
  else {
2135
+ // Reorganization (Flattening)
2136
+ if (!options.keepRoute && deletedFiles.length > 0 && config.routing.mode === 'flat') {
2137
+ const routeParts = normalizedRoute.split('/').filter(Boolean);
2138
+ if (routeParts.length > 1) {
2139
+ for (let i = routeParts.length - 1; i >= 1; i--) {
2140
+ const parentRoute = '/' + routeParts.slice(0, i).join('/');
2141
+ const parentDirName = routeParts.slice(0, i).join('/');
2142
+ const parentDirPath = secureJoin(pagesRoot, parentDirName);
2143
+ if (fs.existsSync(parentDirPath)) {
2144
+ const filesInDir = await promises.readdir(parentDirPath);
2145
+ if (filesInDir.length === 1) {
2146
+ const loneFile = filesInDir[0];
2147
+ const ext = path.extname(loneFile);
2148
+ const indexFile = ext === '.astro' ? config.routing.indexFile : `index${ext}`;
2149
+ if (loneFile === indexFile) {
2150
+ const loneFilePath = path.join(parentDirPath, loneFile);
2151
+ const oldRelative = path.relative(process.cwd(), loneFilePath).replace(/\\/g, '/');
2152
+ if (state.files[oldRelative] && state.files[oldRelative].kind === 'route') {
2153
+ const flatFileName = routeToFilePath(parentRoute, {
2154
+ extension: ext,
2155
+ mode: 'flat'
2156
+ });
2157
+ const flatFilePath = secureJoin(pagesRoot, flatFileName);
2158
+ if (!fs.existsSync(flatFilePath)) {
2159
+ await promises.rename(loneFilePath, flatFilePath);
2160
+ const newRelative = path.relative(process.cwd(), flatFilePath).replace(/\\/g, '/');
2161
+ state.files[newRelative] = { ...state.files[oldRelative] };
2162
+ delete state.files[oldRelative];
2163
+ await updateImportsInFile(flatFilePath, loneFilePath, flatFilePath);
2164
+ // Update hash in state after import updates
2165
+ const content = await promises.readFile(flatFilePath, 'utf-8');
2166
+ state.files[newRelative].hash = calculateHash(content, config.hashing?.normalization);
2167
+ console.log(`✓ Reorganized ${oldRelative} to ${newRelative} (flattened)`);
2168
+ await cleanupEmptyDirs(parentDirPath, pagesRoot);
2169
+ }
2170
+ }
2171
+ }
2172
+ }
2173
+ }
2174
+ }
2175
+ }
2176
+ }
2112
2177
  state.sections = state.sections.filter(s => s.route !== normalizedRoute);
2113
2178
  await saveState(state);
2114
2179
  }
@@ -2121,6 +2186,33 @@ async function removeSectionCommand(route, featurePath, options) {
2121
2186
  throw error;
2122
2187
  }
2123
2188
  }
2189
+ async function updateImportsInFile(filePath, oldFilePath, newFilePath) {
2190
+ if (!fs.existsSync(filePath))
2191
+ return;
2192
+ let content = await promises.readFile(filePath, 'utf-8');
2193
+ const oldDir = path.dirname(oldFilePath);
2194
+ const newDir = path.dirname(newFilePath);
2195
+ if (oldDir === newDir)
2196
+ return;
2197
+ // Find all relative imports
2198
+ const relativeImportRegex = /from\s+['"](\.\.?\/[^'"]+)['"]/g;
2199
+ let match;
2200
+ const replacements = [];
2201
+ while ((match = relativeImportRegex.exec(content)) !== null) {
2202
+ const relativePath = match[1];
2203
+ const absoluteTarget = path.resolve(oldDir, relativePath);
2204
+ const newRelativePath = getRelativeImportPath(newFilePath, absoluteTarget);
2205
+ replacements.push({
2206
+ full: match[0],
2207
+ oldRel: relativePath,
2208
+ newRel: newRelativePath
2209
+ });
2210
+ }
2211
+ for (const repl of replacements) {
2212
+ content = content.replace(repl.full, `from '${repl.newRel}'`);
2213
+ }
2214
+ await promises.writeFile(filePath, content, 'utf-8');
2215
+ }
2124
2216
 
2125
2217
  /**
2126
2218
  * Move a section (route + feature).
@@ -2814,9 +2906,14 @@ async function removeComponentCommand(identifier, options) {
2814
2906
  normalization: config.hashing?.normalization,
2815
2907
  owner: identifier
2816
2908
  });
2817
- if (result.deleted) {
2818
- console.log(`✓ Deleted component: ${componentDir}/`);
2819
- await cleanupEmptyDirs(path.dirname(componentDir), path.join(process.cwd(), config.paths.components));
2909
+ if (result.deleted || (result.reason === 'not-found' && component)) {
2910
+ if (result.deleted) {
2911
+ console.log(`✓ Deleted component: ${componentDir}/`);
2912
+ await cleanupEmptyDirs(path.dirname(componentDir), path.join(process.cwd(), config.paths.components));
2913
+ }
2914
+ else {
2915
+ console.log(`✓ Component ${identifier} removed from state (directory was already missing on disk).`);
2916
+ }
2820
2917
  // Unregister files
2821
2918
  const relComponentPath = path.relative(process.cwd(), componentDir).replace(/\\/g, '/');
2822
2919
  const dirPrefix = relComponentPath + '/';