@oamm/textor 1.0.13 → 1.0.14

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/dist/index.d.ts CHANGED
@@ -53,4 +53,13 @@ declare function pruneMissingCommand(options?: {
53
53
  */
54
54
  declare function renameCommand(type: any, oldName: any, newName: any, options: any): Promise<void>;
55
55
 
56
- export { addSectionCommand, adoptCommand, createComponentCommand, initCommand, listSectionsCommand, moveSectionCommand, normalizeStateCommand, pruneMissingCommand, removeComponentCommand, removeSectionCommand, renameCommand, statusCommand, syncCommand, upgradeConfigCommand, validateStateCommand };
56
+ /**
57
+ * Add a new item (hook, api, service, etc.) to an existing feature or component.
58
+ *
59
+ * @param {string} itemType The type of item to add (e.g., 'api', 'hook', 'service')
60
+ * @param {string} targetName The name of the feature or component
61
+ * @param {Object} options Additional options from Commander
62
+ */
63
+ declare function addItemCommand(itemType: string, targetName: string, options: any): Promise<void>;
64
+
65
+ export { addItemCommand, addSectionCommand, adoptCommand, createComponentCommand, initCommand, listSectionsCommand, moveSectionCommand, normalizeStateCommand, pruneMissingCommand, removeComponentCommand, removeSectionCommand, renameCommand, statusCommand, syncCommand, upgradeConfigCommand, validateStateCommand };
package/dist/index.js CHANGED
@@ -635,14 +635,6 @@ async function safeDelete(filePath, options = {}) {
635
635
  await unlink(filePath);
636
636
  return { deleted: true };
637
637
  }
638
- async function ensureNotExists(filePath, force = false) {
639
- if (existsSync(filePath)) {
640
- if (!force) {
641
- throw new Error(`File already exists: ${filePath}\n` +
642
- `Use --force to overwrite.`);
643
- }
644
- }
645
- }
646
638
  async function ensureDir(dirPath) {
647
639
  await mkdir(dirPath, { recursive: true });
648
640
  }
@@ -1794,29 +1786,35 @@ async function addSectionCommand(route, featurePath, options) {
1794
1786
  }
1795
1787
  }
1796
1788
  }
1797
- await ensureNotExists(featureFilePath, options.force);
1798
- if (shouldCreateIndex)
1799
- await ensureNotExists(indexFilePath, options.force);
1800
- if (shouldCreateContext)
1801
- await ensureNotExists(contextFilePath, options.force);
1802
- if (shouldCreateHooks)
1803
- await ensureNotExists(hookFilePath, options.force);
1804
- if (shouldCreateTests)
1805
- await ensureNotExists(testFilePath, options.force);
1806
- if (shouldCreateTypes)
1807
- await ensureNotExists(typesFilePath, options.force);
1808
- if (shouldCreateApi)
1809
- await ensureNotExists(apiFilePath, options.force);
1810
- if (shouldCreateServices)
1811
- await ensureNotExists(servicesFilePath, options.force);
1812
- if (shouldCreateSchemas)
1813
- await ensureNotExists(schemasFilePath, options.force);
1814
- if (shouldCreateReadme)
1815
- await ensureNotExists(readmeFilePath, options.force);
1816
- if (shouldCreateStories)
1817
- await ensureNotExists(storiesFilePath, options.force);
1818
- if (shouldCreateScriptsDir)
1819
- await ensureNotExists(scriptsIndexPath, options.force);
1789
+ const featureExists = existsSync(featureFilePath);
1790
+ if (featureExists && !options.force) {
1791
+ console.log(`ℹ Feature already exists at ${featureFilePath}. Entering additive mode.`);
1792
+ }
1793
+ // Check sub-items only if not in force mode
1794
+ if (!options.force) {
1795
+ if (shouldCreateIndex && existsSync(indexFilePath))
1796
+ console.log(` - Skipping existing index: ${indexFilePath}`);
1797
+ if (shouldCreateContext && existsSync(contextFilePath))
1798
+ console.log(` - Skipping existing context: ${contextFilePath}`);
1799
+ if (shouldCreateHooks && existsSync(hookFilePath))
1800
+ console.log(` - Skipping existing hook: ${hookFilePath}`);
1801
+ if (shouldCreateTests && existsSync(testFilePath))
1802
+ console.log(` - Skipping existing test: ${testFilePath}`);
1803
+ if (shouldCreateTypes && existsSync(typesFilePath))
1804
+ console.log(` - Skipping existing types: ${typesFilePath}`);
1805
+ if (shouldCreateApi && existsSync(apiFilePath))
1806
+ console.log(` - Skipping existing api: ${apiFilePath}`);
1807
+ if (shouldCreateServices && existsSync(servicesFilePath))
1808
+ console.log(` - Skipping existing services: ${servicesFilePath}`);
1809
+ if (shouldCreateSchemas && existsSync(schemasFilePath))
1810
+ console.log(` - Skipping existing schemas: ${schemasFilePath}`);
1811
+ if (shouldCreateReadme && existsSync(readmeFilePath))
1812
+ console.log(` - Skipping existing readme: ${readmeFilePath}`);
1813
+ if (shouldCreateStories && existsSync(storiesFilePath))
1814
+ console.log(` - Skipping existing stories: ${storiesFilePath}`);
1815
+ if (shouldCreateScriptsDir && existsSync(scriptsIndexPath))
1816
+ console.log(` - Skipping existing scripts: ${scriptsIndexPath}`);
1817
+ }
1820
1818
  let layoutImportPath = null;
1821
1819
  const cliProps = options.prop || {};
1822
1820
  const rawLayoutProps = { ...configLayoutProps, ...cliProps };
@@ -1938,15 +1936,17 @@ async function addSectionCommand(route, featurePath, options) {
1938
1936
  if (shouldCreateTypes)
1939
1937
  await ensureDir(typesDirInside);
1940
1938
  const featureSignature = getSignature(config, config.naming.featureExtension === '.astro' ? 'astro' : 'tsx');
1941
- const featureHash = await writeFileWithSignature(featureFilePath, featureContent, featureSignature, config.hashing?.normalization);
1942
- await registerFile(featureFilePath, {
1943
- kind: 'feature',
1944
- template: 'feature',
1945
- hash: featureHash,
1946
- owner: normalizedRoute
1947
- });
1948
- writtenFiles.push(featureFilePath);
1949
- if (shouldCreateScriptsDir) {
1939
+ if (!featureExists || options.force) {
1940
+ const featureHash = await writeFileWithSignature(featureFilePath, featureContent, featureSignature, config.hashing?.normalization);
1941
+ await registerFile(featureFilePath, {
1942
+ kind: 'feature',
1943
+ template: 'feature',
1944
+ hash: featureHash,
1945
+ owner: normalizedRoute
1946
+ });
1947
+ writtenFiles.push(featureFilePath);
1948
+ }
1949
+ if (shouldCreateScriptsDir && (!existsSync(scriptsIndexPath) || options.force)) {
1950
1950
  const hash = await writeFileWithSignature(scriptsIndexPath, generateScriptsIndexTemplate(), getSignature(config, 'typescript'), config.hashing?.normalization);
1951
1951
  await registerFile(scriptsIndexPath, {
1952
1952
  kind: 'feature-file',
@@ -1956,7 +1956,7 @@ async function addSectionCommand(route, featurePath, options) {
1956
1956
  });
1957
1957
  writtenFiles.push(scriptsIndexPath);
1958
1958
  }
1959
- if (shouldCreateIndex) {
1959
+ if (shouldCreateIndex && (!existsSync(indexFilePath) || options.force)) {
1960
1960
  const indexContent = generateIndexTemplate(featureComponentName, config.naming.featureExtension);
1961
1961
  const hash = await writeFileWithSignature(indexFilePath, indexContent, getSignature(config, 'typescript'), config.hashing?.normalization);
1962
1962
  await registerFile(indexFilePath, {
@@ -1967,7 +1967,7 @@ async function addSectionCommand(route, featurePath, options) {
1967
1967
  });
1968
1968
  writtenFiles.push(indexFilePath);
1969
1969
  }
1970
- if (shouldCreateApi) {
1970
+ if (shouldCreateApi && (!existsSync(apiFilePath) || options.force)) {
1971
1971
  const apiContent = generateApiTemplate(featureComponentName);
1972
1972
  const hash = await writeFileWithSignature(apiFilePath, apiContent, getSignature(config, 'typescript'), config.hashing?.normalization);
1973
1973
  await registerFile(apiFilePath, {
@@ -1978,7 +1978,7 @@ async function addSectionCommand(route, featurePath, options) {
1978
1978
  });
1979
1979
  writtenFiles.push(apiFilePath);
1980
1980
  }
1981
- if (shouldCreateServices) {
1981
+ if (shouldCreateServices && (!existsSync(servicesFilePath) || options.force)) {
1982
1982
  const servicesContent = generateServiceTemplate(featureComponentName);
1983
1983
  const hash = await writeFileWithSignature(servicesFilePath, servicesContent, getSignature(config, 'typescript'), config.hashing?.normalization);
1984
1984
  await registerFile(servicesFilePath, {
@@ -1989,7 +1989,7 @@ async function addSectionCommand(route, featurePath, options) {
1989
1989
  });
1990
1990
  writtenFiles.push(servicesFilePath);
1991
1991
  }
1992
- if (shouldCreateSchemas) {
1992
+ if (shouldCreateSchemas && (!existsSync(schemasFilePath) || options.force)) {
1993
1993
  const schemasContent = generateSchemaTemplate(featureComponentName);
1994
1994
  const hash = await writeFileWithSignature(schemasFilePath, schemasContent, getSignature(config, 'typescript'), config.hashing?.normalization);
1995
1995
  await registerFile(schemasFilePath, {
@@ -2000,7 +2000,7 @@ async function addSectionCommand(route, featurePath, options) {
2000
2000
  });
2001
2001
  writtenFiles.push(schemasFilePath);
2002
2002
  }
2003
- if (shouldCreateHooks) {
2003
+ if (shouldCreateHooks && (!existsSync(hookFilePath) || options.force)) {
2004
2004
  const hookName = getHookFunctionName(featureComponentName);
2005
2005
  const hookContent = generateHookTemplate(featureComponentName, hookName);
2006
2006
  const hash = await writeFileWithSignature(hookFilePath, hookContent, getSignature(config, 'typescript'), config.hashing?.normalization);
@@ -2012,7 +2012,7 @@ async function addSectionCommand(route, featurePath, options) {
2012
2012
  });
2013
2013
  writtenFiles.push(hookFilePath);
2014
2014
  }
2015
- if (shouldCreateContext) {
2015
+ if (shouldCreateContext && (!existsSync(contextFilePath) || options.force)) {
2016
2016
  const contextContent = generateContextTemplate(featureComponentName);
2017
2017
  const hash = await writeFileWithSignature(contextFilePath, contextContent, getSignature(config, 'typescript'), config.hashing?.normalization);
2018
2018
  await registerFile(contextFilePath, {
@@ -2023,7 +2023,7 @@ async function addSectionCommand(route, featurePath, options) {
2023
2023
  });
2024
2024
  writtenFiles.push(contextFilePath);
2025
2025
  }
2026
- if (shouldCreateTests) {
2026
+ if (shouldCreateTests && (!existsSync(testFilePath) || options.force)) {
2027
2027
  const relativeFeaturePath = `./${path.basename(featureFilePath)}`;
2028
2028
  const testContent = generateTestTemplate(featureComponentName, relativeFeaturePath);
2029
2029
  const hash = await writeFileWithSignature(testFilePath, testContent, getSignature(config, 'typescript'), config.hashing?.normalization);
@@ -2035,7 +2035,7 @@ async function addSectionCommand(route, featurePath, options) {
2035
2035
  });
2036
2036
  writtenFiles.push(testFilePath);
2037
2037
  }
2038
- if (shouldCreateTypes) {
2038
+ if (shouldCreateTypes && (!existsSync(typesFilePath) || options.force)) {
2039
2039
  const typesContent = generateTypesTemplate(featureComponentName);
2040
2040
  const hash = await writeFileWithSignature(typesFilePath, typesContent, getSignature(config, 'typescript'), config.hashing?.normalization);
2041
2041
  await registerFile(typesFilePath, {
@@ -2046,7 +2046,7 @@ async function addSectionCommand(route, featurePath, options) {
2046
2046
  });
2047
2047
  writtenFiles.push(typesFilePath);
2048
2048
  }
2049
- if (shouldCreateReadme) {
2049
+ if (shouldCreateReadme && (!existsSync(readmeFilePath) || options.force)) {
2050
2050
  const readmeContent = generateReadmeTemplate(featureComponentName);
2051
2051
  const hash = await writeFileWithSignature(readmeFilePath, readmeContent, getSignature(config, 'astro'), config.hashing?.normalization);
2052
2052
  await registerFile(readmeFilePath, {
@@ -2057,7 +2057,7 @@ async function addSectionCommand(route, featurePath, options) {
2057
2057
  });
2058
2058
  writtenFiles.push(readmeFilePath);
2059
2059
  }
2060
- if (shouldCreateStories) {
2060
+ if (shouldCreateStories && (!existsSync(storiesFilePath) || options.force)) {
2061
2061
  const relativePath = `./${path.basename(featureFilePath)}`;
2062
2062
  const storiesContent = generateStoriesTemplate(featureComponentName, relativePath);
2063
2063
  const hash = await writeFileWithSignature(storiesFilePath, storiesContent, getSignature(config, 'typescript'), config.hashing?.normalization);
@@ -2870,30 +2870,37 @@ async function createComponentCommand(componentName, options) {
2870
2870
  console.log(` Sub-components: ${subComponentsDir}/`);
2871
2871
  return;
2872
2872
  }
2873
- await ensureNotExists(componentFilePath, options.force);
2874
- await ensureNotExists(indexFilePath, options.force);
2875
- if (shouldCreateContext)
2876
- await ensureNotExists(contextFilePath, options.force);
2877
- if (shouldCreateHook)
2878
- await ensureNotExists(hookFilePath, options.force);
2879
- if (shouldCreateTests)
2880
- await ensureNotExists(testFilePath, options.force);
2881
- if (shouldCreateConfig)
2882
- await ensureNotExists(configFilePath, options.force);
2883
- if (shouldCreateConstants)
2884
- await ensureNotExists(constantsFilePath, options.force);
2885
- if (shouldCreateTypes)
2886
- await ensureNotExists(typesFilePath, options.force);
2887
- if (shouldCreateApi)
2888
- await ensureNotExists(apiFilePath, options.force);
2889
- if (shouldCreateServices)
2890
- await ensureNotExists(servicesFilePath, options.force);
2891
- if (shouldCreateSchemas)
2892
- await ensureNotExists(schemasFilePath, options.force);
2893
- if (shouldCreateReadme)
2894
- await ensureNotExists(readmeFilePath, options.force);
2895
- if (shouldCreateStories)
2896
- await ensureNotExists(storiesFilePath, options.force);
2873
+ const componentExists = existsSync(componentFilePath);
2874
+ if (componentExists && !options.force) {
2875
+ console.log(`ℹ Component already exists at ${componentFilePath}. Entering additive mode.`);
2876
+ }
2877
+ // Check sub-items only if not in force mode
2878
+ if (!options.force) {
2879
+ if (existsSync(indexFilePath))
2880
+ console.log(` - Skipping existing index: ${indexFilePath}`);
2881
+ if (shouldCreateContext && existsSync(contextFilePath))
2882
+ console.log(` - Skipping existing context: ${contextFilePath}`);
2883
+ if (shouldCreateHook && existsSync(hookFilePath))
2884
+ console.log(` - Skipping existing hook: ${hookFilePath}`);
2885
+ if (shouldCreateTests && existsSync(testFilePath))
2886
+ console.log(` - Skipping existing test: ${testFilePath}`);
2887
+ if (shouldCreateConfig && existsSync(configFilePath))
2888
+ console.log(` - Skipping existing config: ${configFilePath}`);
2889
+ if (shouldCreateConstants && existsSync(constantsFilePath))
2890
+ console.log(` - Skipping existing constants: ${constantsFilePath}`);
2891
+ if (shouldCreateTypes && existsSync(typesFilePath))
2892
+ console.log(` - Skipping existing types: ${typesFilePath}`);
2893
+ if (shouldCreateApi && existsSync(apiFilePath))
2894
+ console.log(` - Skipping existing api: ${apiFilePath}`);
2895
+ if (shouldCreateServices && existsSync(servicesFilePath))
2896
+ console.log(` - Skipping existing services: ${servicesFilePath}`);
2897
+ if (shouldCreateSchemas && existsSync(schemasFilePath))
2898
+ console.log(` - Skipping existing schemas: ${schemasFilePath}`);
2899
+ if (shouldCreateReadme && existsSync(readmeFilePath))
2900
+ console.log(` - Skipping existing readme: ${readmeFilePath}`);
2901
+ if (shouldCreateStories && existsSync(storiesFilePath))
2902
+ console.log(` - Skipping existing stories: ${storiesFilePath}`);
2903
+ }
2897
2904
  await ensureDir(componentDir);
2898
2905
  if (shouldCreateSubComponentsDir)
2899
2906
  await ensureDir(subComponentsDir);
@@ -2917,24 +2924,29 @@ async function createComponentCommand(componentName, options) {
2917
2924
  await ensureDir(schemasDirInside);
2918
2925
  const componentContent = generateComponentTemplate(normalizedName, framework, config.naming.componentExtension);
2919
2926
  const signature = getSignature(config, config.naming.componentExtension === '.astro' ? 'astro' : 'tsx');
2920
- const componentHash = await writeFileWithSignature(componentFilePath, componentContent, signature, config.hashing?.normalization);
2921
- await registerFile(componentFilePath, {
2922
- kind: 'component',
2923
- template: 'component',
2924
- hash: componentHash,
2925
- owner: normalizedName
2926
- });
2927
- const writtenFiles = [componentFilePath];
2928
- const indexContent = generateIndexTemplate(normalizedName, config.naming.componentExtension);
2929
- const indexHash = await writeFileWithSignature(indexFilePath, indexContent, getSignature(config, 'typescript'), config.hashing?.normalization);
2930
- await registerFile(indexFilePath, {
2931
- kind: 'component-file',
2932
- template: 'index',
2933
- hash: indexHash,
2934
- owner: normalizedName
2935
- });
2936
- writtenFiles.push(indexFilePath);
2937
- if (shouldCreateTypes) {
2927
+ const writtenFiles = [];
2928
+ if (!componentExists || options.force) {
2929
+ const componentHash = await writeFileWithSignature(componentFilePath, componentContent, signature, config.hashing?.normalization);
2930
+ await registerFile(componentFilePath, {
2931
+ kind: 'component',
2932
+ template: 'component',
2933
+ hash: componentHash,
2934
+ owner: normalizedName
2935
+ });
2936
+ writtenFiles.push(componentFilePath);
2937
+ }
2938
+ if (!existsSync(indexFilePath) || options.force) {
2939
+ const indexContent = generateIndexTemplate(normalizedName, config.naming.componentExtension);
2940
+ const indexHash = await writeFileWithSignature(indexFilePath, indexContent, getSignature(config, 'typescript'), config.hashing?.normalization);
2941
+ await registerFile(indexFilePath, {
2942
+ kind: 'component-file',
2943
+ template: 'index',
2944
+ hash: indexHash,
2945
+ owner: normalizedName
2946
+ });
2947
+ writtenFiles.push(indexFilePath);
2948
+ }
2949
+ if (shouldCreateTypes && (!existsSync(typesFilePath) || options.force)) {
2938
2950
  const typesContent = generateTypesTemplate(normalizedName);
2939
2951
  const hash = await writeFileWithSignature(typesFilePath, typesContent, getSignature(config, 'typescript'), config.hashing?.normalization);
2940
2952
  await registerFile(typesFilePath, {
@@ -2945,7 +2957,7 @@ async function createComponentCommand(componentName, options) {
2945
2957
  });
2946
2958
  writtenFiles.push(typesFilePath);
2947
2959
  }
2948
- if (shouldCreateContext) {
2960
+ if (shouldCreateContext && (!existsSync(contextFilePath) || options.force)) {
2949
2961
  const contextContent = generateContextTemplate(normalizedName);
2950
2962
  const hash = await writeFileWithSignature(contextFilePath, contextContent, getSignature(config, 'typescript'), config.hashing?.normalization);
2951
2963
  await registerFile(contextFilePath, {
@@ -2956,7 +2968,7 @@ async function createComponentCommand(componentName, options) {
2956
2968
  });
2957
2969
  writtenFiles.push(contextFilePath);
2958
2970
  }
2959
- if (shouldCreateHook) {
2971
+ if (shouldCreateHook && (!existsSync(hookFilePath) || options.force)) {
2960
2972
  const hookName = getHookFunctionName(normalizedName);
2961
2973
  const hookContent = generateHookTemplate(normalizedName, hookName);
2962
2974
  const hash = await writeFileWithSignature(hookFilePath, hookContent, getSignature(config, 'typescript'), config.hashing?.normalization);
@@ -2968,7 +2980,7 @@ async function createComponentCommand(componentName, options) {
2968
2980
  });
2969
2981
  writtenFiles.push(hookFilePath);
2970
2982
  }
2971
- if (shouldCreateTests) {
2983
+ if (shouldCreateTests && (!existsSync(testFilePath) || options.force)) {
2972
2984
  const relativeComponentPath = `../${normalizedName}${config.naming.componentExtension}`;
2973
2985
  const testContent = generateTestTemplate(normalizedName, relativeComponentPath);
2974
2986
  const hash = await writeFileWithSignature(testFilePath, testContent, getSignature(config, 'typescript'), config.hashing?.normalization);
@@ -2980,7 +2992,7 @@ async function createComponentCommand(componentName, options) {
2980
2992
  });
2981
2993
  writtenFiles.push(testFilePath);
2982
2994
  }
2983
- if (shouldCreateConfig) {
2995
+ if (shouldCreateConfig && (!existsSync(configFilePath) || options.force)) {
2984
2996
  const configContent = generateConfigTemplate(normalizedName);
2985
2997
  const hash = await writeFileWithSignature(configFilePath, configContent, getSignature(config, 'typescript'), config.hashing?.normalization);
2986
2998
  await registerFile(configFilePath, {
@@ -2991,7 +3003,7 @@ async function createComponentCommand(componentName, options) {
2991
3003
  });
2992
3004
  writtenFiles.push(configFilePath);
2993
3005
  }
2994
- if (shouldCreateConstants) {
3006
+ if (shouldCreateConstants && (!existsSync(constantsFilePath) || options.force)) {
2995
3007
  const constantsContent = generateConstantsTemplate(normalizedName);
2996
3008
  const hash = await writeFileWithSignature(constantsFilePath, constantsContent, getSignature(config, 'typescript'), config.hashing?.normalization);
2997
3009
  await registerFile(constantsFilePath, {
@@ -3002,7 +3014,7 @@ async function createComponentCommand(componentName, options) {
3002
3014
  });
3003
3015
  writtenFiles.push(constantsFilePath);
3004
3016
  }
3005
- if (shouldCreateApi) {
3017
+ if (shouldCreateApi && (!existsSync(apiFilePath) || options.force)) {
3006
3018
  const apiContent = generateApiTemplate(normalizedName);
3007
3019
  const hash = await writeFileWithSignature(apiFilePath, apiContent, getSignature(config, 'typescript'), config.hashing?.normalization);
3008
3020
  await registerFile(apiFilePath, {
@@ -3013,7 +3025,7 @@ async function createComponentCommand(componentName, options) {
3013
3025
  });
3014
3026
  writtenFiles.push(apiFilePath);
3015
3027
  }
3016
- if (shouldCreateServices) {
3028
+ if (shouldCreateServices && (!existsSync(servicesFilePath) || options.force)) {
3017
3029
  const servicesContent = generateServiceTemplate(normalizedName);
3018
3030
  const hash = await writeFileWithSignature(servicesFilePath, servicesContent, getSignature(config, 'typescript'), config.hashing?.normalization);
3019
3031
  await registerFile(servicesFilePath, {
@@ -3024,7 +3036,7 @@ async function createComponentCommand(componentName, options) {
3024
3036
  });
3025
3037
  writtenFiles.push(servicesFilePath);
3026
3038
  }
3027
- if (shouldCreateSchemas) {
3039
+ if (shouldCreateSchemas && (!existsSync(schemasFilePath) || options.force)) {
3028
3040
  const schemasContent = generateSchemaTemplate(normalizedName);
3029
3041
  const hash = await writeFileWithSignature(schemasFilePath, schemasContent, getSignature(config, 'typescript'), config.hashing?.normalization);
3030
3042
  await registerFile(schemasFilePath, {
@@ -3035,7 +3047,7 @@ async function createComponentCommand(componentName, options) {
3035
3047
  });
3036
3048
  writtenFiles.push(schemasFilePath);
3037
3049
  }
3038
- if (shouldCreateReadme) {
3050
+ if (shouldCreateReadme && (!existsSync(readmeFilePath) || options.force)) {
3039
3051
  const readmeContent = generateReadmeTemplate(normalizedName);
3040
3052
  const hash = await writeFileWithSignature(readmeFilePath, readmeContent, getSignature(config, 'astro'), config.hashing?.normalization);
3041
3053
  await registerFile(readmeFilePath, {
@@ -3046,7 +3058,7 @@ async function createComponentCommand(componentName, options) {
3046
3058
  });
3047
3059
  writtenFiles.push(readmeFilePath);
3048
3060
  }
3049
- if (shouldCreateStories) {
3061
+ if (shouldCreateStories && (!existsSync(storiesFilePath) || options.force)) {
3050
3062
  const relativePath = `./${normalizedName}${config.naming.componentExtension}`;
3051
3063
  const storiesContent = generateStoriesTemplate(normalizedName, relativePath);
3052
3064
  const hash = await writeFileWithSignature(storiesFilePath, storiesContent, getSignature(config, 'typescript'), config.hashing?.normalization);
@@ -3985,5 +3997,59 @@ async function renameComponent(oldName, newName, options) {
3985
3997
  console.log(`✓ Renamed component ${normalizedOldName} to ${normalizedNewName}`);
3986
3998
  }
3987
3999
 
3988
- export { addSectionCommand, adoptCommand, createComponentCommand, initCommand, listSectionsCommand, moveSectionCommand, normalizeStateCommand, pruneMissingCommand, removeComponentCommand, removeSectionCommand, renameCommand, statusCommand, syncCommand, upgradeConfigCommand, validateStateCommand };
4000
+ /**
4001
+ * Add a new item (hook, api, service, etc.) to an existing feature or component.
4002
+ *
4003
+ * @param {string} itemType The type of item to add (e.g., 'api', 'hook', 'service')
4004
+ * @param {string} targetName The name of the feature or component
4005
+ * @param {Object} options Additional options from Commander
4006
+ */
4007
+ async function addItemCommand(itemType, targetName, options) {
4008
+ try {
4009
+ const state = await loadState();
4010
+ // Normalize itemType
4011
+ let normalizedItem = itemType.toLowerCase();
4012
+ if (normalizedItem === 'test')
4013
+ normalizedItem = 'tests';
4014
+ if (normalizedItem === 'service')
4015
+ normalizedItem = 'services';
4016
+ if (normalizedItem === 'schema')
4017
+ normalizedItem = 'schemas';
4018
+ if (normalizedItem === 'hook')
4019
+ normalizedItem = 'hooks'; // for add-section
4020
+ // Try to find as section (feature) first
4021
+ let section = findSection(state, targetName);
4022
+ let component = findComponent(state, targetName);
4023
+ // If not found by exact name, try to find by featurePath or part of it
4024
+ if (!section && !component) {
4025
+ section = state.sections.find(s => s.featurePath === targetName || s.featurePath.endsWith('/' + targetName));
4026
+ }
4027
+ if (!section && !component) {
4028
+ throw new Error(`Target not found in state: "${targetName}". Please use "add-section" or "create-component" directly if it's not managed by Textor.`);
4029
+ }
4030
+ const flags = { [normalizedItem]: true };
4031
+ // Also set singular for create-component which uses 'hook'
4032
+ if (normalizedItem === 'hooks')
4033
+ flags.hook = true;
4034
+ if (section) {
4035
+ console.log(`ℹ Adding ${normalizedItem} to feature: ${section.featurePath}`);
4036
+ return await addSectionCommand(undefined, section.featurePath, { ...options, ...flags });
4037
+ }
4038
+ if (component) {
4039
+ console.log(`ℹ Adding ${normalizedItem} to component: ${component.name}`);
4040
+ // For create-component, we might need to be careful with flags that are on by default
4041
+ // but getEffectiveOptions should handle it if we pass them explicitly as true.
4042
+ return await createComponentCommand(component.name, { ...options, ...flags });
4043
+ }
4044
+ }
4045
+ catch (error) {
4046
+ console.error('Error:', error.message);
4047
+ if (typeof process.exit === 'function' && process.env.NODE_ENV !== 'test') {
4048
+ process.exit(1);
4049
+ }
4050
+ throw error;
4051
+ }
4052
+ }
4053
+
4054
+ export { addItemCommand, addSectionCommand, adoptCommand, createComponentCommand, initCommand, listSectionsCommand, moveSectionCommand, normalizeStateCommand, pruneMissingCommand, removeComponentCommand, removeSectionCommand, renameCommand, statusCommand, syncCommand, upgradeConfigCommand, validateStateCommand };
3989
4055
  //# sourceMappingURL=index.js.map