@starodubenko/fsd-gen 0.1.1 → 1.1.0-0

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.
Files changed (93) hide show
  1. package/README.md +185 -1
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +105 -0
  5. package/dist/config/defineConfig.d.ts +1 -1
  6. package/dist/config/defineConfig.d.ts.map +1 -1
  7. package/dist/config/types.d.ts +59 -1
  8. package/dist/config/types.d.ts.map +1 -1
  9. package/dist/index.d.ts +3 -2
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/lib/barrels/updateBarrels.d.ts.map +1 -1
  12. package/dist/lib/barrels/updateBarrels.js +6 -4
  13. package/dist/lib/cli/handlers.d.ts +25 -0
  14. package/dist/lib/cli/handlers.d.ts.map +1 -0
  15. package/dist/lib/cli/handlers.js +97 -0
  16. package/dist/lib/cli/prompts.d.ts +21 -0
  17. package/dist/lib/cli/prompts.d.ts.map +1 -0
  18. package/dist/lib/cli/prompts.js +80 -0
  19. package/dist/lib/generators/generate.d.ts +1 -5
  20. package/dist/lib/generators/generate.d.ts.map +1 -1
  21. package/dist/lib/generators/generate.js +2 -2
  22. package/dist/lib/generators/generatePreset.d.ts +2 -2
  23. package/dist/lib/generators/generatePreset.d.ts.map +1 -1
  24. package/dist/lib/generators/generatePreset.js +10 -74
  25. package/dist/lib/generators/presetExecutionHelpers.d.ts +20 -0
  26. package/dist/lib/generators/presetExecutionHelpers.d.ts.map +1 -0
  27. package/dist/lib/generators/presetExecutionHelpers.js +59 -0
  28. package/dist/lib/helpers/presetHelpers.d.ts +1 -27
  29. package/dist/lib/helpers/presetHelpers.d.ts.map +1 -1
  30. package/dist/lib/helpers/presetHelpers.js +24 -9
  31. package/dist/lib/helpers/presetHelpers.spec.d.ts +2 -0
  32. package/dist/lib/helpers/presetHelpers.spec.d.ts.map +1 -0
  33. package/dist/lib/helpers/presetHelpers.spec.js +36 -0
  34. package/dist/lib/helpers/templateHelpers.d.ts +20 -0
  35. package/dist/lib/helpers/templateHelpers.d.ts.map +1 -0
  36. package/dist/lib/helpers/templateHelpers.js +23 -0
  37. package/dist/lib/jsx/components.d.ts +38 -0
  38. package/dist/lib/jsx/components.d.ts.map +1 -0
  39. package/dist/lib/jsx/components.js +40 -0
  40. package/dist/lib/jsx/jsx-runtime.d.ts +20 -0
  41. package/dist/lib/jsx/jsx-runtime.d.ts.map +1 -0
  42. package/dist/lib/jsx/jsx-runtime.js +7 -0
  43. package/dist/lib/jsx/renderer.d.ts +2 -0
  44. package/dist/lib/jsx/renderer.d.ts.map +1 -0
  45. package/dist/lib/jsx/renderer.js +24 -0
  46. package/dist/lib/preset/actionExecution.d.ts +2 -2
  47. package/dist/lib/preset/actionExecution.d.ts.map +1 -1
  48. package/dist/lib/preset/actionExecution.js +43 -7
  49. package/dist/lib/preset/actionExecution.spec.d.ts +2 -0
  50. package/dist/lib/preset/actionExecution.spec.d.ts.map +1 -0
  51. package/dist/lib/preset/actionExecution.spec.js +178 -0
  52. package/dist/lib/preset/presetDiscovery.d.ts +6 -34
  53. package/dist/lib/preset/presetDiscovery.d.ts.map +1 -1
  54. package/dist/lib/preset/presetDiscovery.js +42 -171
  55. package/dist/lib/preset/presetLoading.d.ts.map +1 -1
  56. package/dist/lib/preset/presetLoading.js +2 -1
  57. package/dist/lib/reverse/analyze.d.ts +6 -0
  58. package/dist/lib/reverse/analyze.d.ts.map +1 -0
  59. package/dist/lib/reverse/analyze.js +55 -0
  60. package/dist/lib/reverse/analyzeHelpers.d.ts +19 -0
  61. package/dist/lib/reverse/analyzeHelpers.d.ts.map +1 -0
  62. package/dist/lib/reverse/analyzeHelpers.js +38 -0
  63. package/dist/lib/reverse/build.d.ts +6 -0
  64. package/dist/lib/reverse/build.d.ts.map +1 -0
  65. package/dist/lib/reverse/build.js +57 -0
  66. package/dist/lib/reverse/buildHelpers.d.ts +41 -0
  67. package/dist/lib/reverse/buildHelpers.d.ts.map +1 -0
  68. package/dist/lib/reverse/buildHelpers.js +173 -0
  69. package/dist/lib/reverse/init.d.ts +2 -0
  70. package/dist/lib/reverse/init.d.ts.map +1 -0
  71. package/dist/lib/reverse/init.js +30 -0
  72. package/dist/lib/reverse/types.d.ts +47 -0
  73. package/dist/lib/reverse/types.d.ts.map +1 -0
  74. package/dist/lib/reverse/types.js +1 -0
  75. package/dist/lib/templates/templateLoader.d.ts +7 -5
  76. package/dist/lib/templates/templateLoader.d.ts.map +1 -1
  77. package/dist/lib/templates/templateLoader.js +92 -9
  78. package/package.json +4 -4
  79. package/templates/entity/model-ui-basic/Component.tsx +18 -7
  80. package/templates/feature/ui-model-basic/Component.tsx +18 -7
  81. package/templates/page/ui-basic/Component.tsx +18 -7
  82. package/templates/preset/table/entity/model.ts +10 -4
  83. package/templates/preset/table/feature/buttons.tsx +12 -6
  84. package/templates/preset/table/page/page.tsx +30 -8
  85. package/templates/preset/table/widget/table.tsx +28 -11
  86. package/templates/shared/ui-basic/Component.tsx +17 -6
  87. package/templates/widget/ui-basic/Component.tsx +18 -7
  88. package/cli.js +0 -114
  89. package/templates/entity/model-ui-basic/Component.styles.ts +0 -1
  90. package/templates/feature/ui-model-basic/Component.styles.ts +0 -1
  91. package/templates/page/ui-basic/Component.styles.ts +0 -1
  92. package/templates/shared/ui-basic/Component.styles.ts +0 -1
  93. package/templates/widget/ui-basic/Component.styles.ts +0 -1
package/README.md CHANGED
@@ -29,7 +29,7 @@ npx @starodubenko/fsd-gen generate <layer> <slice> [name]
29
29
  npx @starodubenko/fsd-gen generate entity User UserCard
30
30
  ```
31
31
 
32
- ### Using Presets
32
+ ### Generating from Presets
33
33
 
34
34
  Presets generate multiple related components across layers.
35
35
 
@@ -37,6 +37,18 @@ Presets generate multiple related components across layers.
37
37
  npx @starodubenko/fsd-gen preset table Product
38
38
  ```
39
39
 
40
+ ### Reverse Preset Generation (Beta)
41
+
42
+ Reverse engineer existing code into reusable presets.
43
+
44
+ 1. **Initialize**: `fsd-gen reverse:init <preset-name> [--mode short|ejected]`
45
+ 2. **Analyze**: `fsd-gen reverse:analyze <preset-name>`
46
+ 3. **Build**: `fsd-gen reverse:build <preset-name> [--mode short|ejected]`
47
+
48
+ #### Modes
49
+ - **short** (default): Generates a thin `preset.ts` that auto-discovers templates at runtime.
50
+ - **ejected**: Compiles and copies all source files into the preset folder as static templates.
51
+
40
52
  ## ⚙️ Configuration
41
53
 
42
54
  Create an `fsdgen.config.ts` in your project root:
@@ -45,17 +57,189 @@ Create an `fsdgen.config.ts` in your project root:
45
57
  import { defineConfig } from '@starodubenko/fsd-gen';
46
58
 
47
59
  export default defineConfig({
60
+ /**
61
+ * Root directory of the source code.
62
+ * Defaults to "src".
63
+ */
48
64
  rootDir: 'src',
65
+
66
+ /**
67
+ * Alias configuration.
68
+ * Maps import aliases to their relative paths from root.
69
+ */
49
70
  aliases: {
50
71
  '@entities': './src/entities',
51
72
  '@features': './src/features',
52
73
  '@widgets': './src/widgets',
53
74
  '@pages': './src/pages',
54
75
  '@shared': './src/shared',
76
+ },
77
+
78
+ /**
79
+ * Directory containing custom templates.
80
+ * Can be relative to the config file.
81
+ */
82
+ templatesDir: './.fsd-templates',
83
+
84
+ /**
85
+ * Naming convention enforcement.
86
+ * "strict" | "warn" | "off"
87
+ */
88
+ naming: 'warn',
89
+ });
90
+ ```
91
+
92
+ ## 📂 Template Structure
93
+
94
+ To customize templates, creating a `templatesDir` (e.g., `.fsd-templates`) allows you to override default templates. The structure should mirror the generator's internal organization:
95
+
96
+ ```
97
+ .fsd-templates/
98
+ ├── entity/
99
+ │ └── model-ui/ # Template name (e.g., used by default or specified)
100
+ │ └── sub/ # Optional subdirectory
101
+ │ └── Component.tsx
102
+ ├── feature/
103
+ │ └── ...
104
+ ├── page/
105
+ │ └── ...
106
+ ├── widget/
107
+ │ └── ...
108
+ └── preset/
109
+ └── my-preset/ # Custom preset
110
+ ├── entity/
111
+ ├── feature/
112
+ └── preset.ts # Preset definition
113
+ ```
114
+
115
+ ## 📝 Templated Component Example
116
+
117
+ Templates can either be standard files using **EJS** syntax or **TypeScript functions** that return the file content string.
118
+
119
+
120
+ **Example: `Component.tsx`**
121
+
122
+ ```tsx
123
+ import type { GeneratorContext } from '@starodubenko/fsd-gen';
124
+
125
+ export default ({
126
+ base: { baseName },
127
+ template: { componentName },
128
+ layer: {
129
+ entity: { apiPath: apiImportPath, importPath: entityImportPath }
55
130
  }
131
+ }: GeneratorContext) => `
132
+ import styled from '@emotion/styled';
133
+ import type { ${baseName} } from '${entityImportPath}/model/model';
134
+ import { useCreate${baseName} } from '${apiImportPath}';
135
+
136
+ const Button = styled.button\`
137
+ padding: 0.5rem 1rem;
138
+ margin: 0 0.5rem;
139
+ border-radius: 4px;
140
+ border: none;
141
+ background-color: #007bff;
142
+ color: white;
143
+ cursor: pointer;
144
+
145
+ &:disabled {
146
+ background-color: #ccc;
147
+ cursor: not-allowed;
148
+ }
149
+
150
+ &:hover:not(:disabled) {
151
+ background-color: #0056b3;
152
+ }
153
+ \`;
154
+
155
+ export const ${componentName}Button = () => {
156
+ const { mutate, isLoading } = useCreate${baseName}();
157
+ return (
158
+ <Button onClick={() => mutate({ /* mock data */ } as unknown as Omit<${baseName}, 'id'>)} disabled={isLoading}>
159
+ {isLoading ? 'Creating...' : 'Create ${baseName}'}
160
+ </Button>
161
+ );
162
+ };
163
+ `;
164
+ ```
165
+
166
+ **Available Variables (`GeneratorContext`):**
167
+
168
+ Assuming input name is **"User"** and default configuration:
169
+
170
+ | Variable | Description | Example Value |
171
+ | :--- | :--- | :--- |
172
+ | `componentName` | Name of the component being generated | `UserCard` |
173
+ | `sliceName` | Name of the current slice | `User` |
174
+ | `layer` | Current FSD layer | `entity` |
175
+ | `base.name` | Original user input name | `User` |
176
+ | `layer.entity.importPath` | Resolved import path for entity | `@entities/User` |
177
+ | `layer.features.slice` | Feature slice name (with prefix) | `ManageUser` |
178
+ | `layer.features.importPath` | Feature import path | `@features/ManageUser` |
179
+ | `layer.widget.slice` | Widget slice name | `User` |
180
+ | `layer.widget.importPath` | Widget import path | `@widgets/User` |
181
+ | `layer.page.slice` | Page slice name (with suffix) | `UserPage` |
182
+ | `layer.page.importPath` | Page import path | `@pages/UserPage` |
183
+
184
+ > **Note:** Paths vary based on your `aliases` configuration.
185
+
186
+ ## 🔧 Advanced Preset Configuration
187
+
188
+ You can define sophisticated presets with custom logic, naming conventions, and routing.
189
+
190
+ **Example `preset.ts`:**
191
+
192
+ ```typescript
193
+ import { definePreset, createPresetHelpers } from '@starodubenko/fsd-gen';
194
+
195
+ export default definePreset(({ name, config }) => {
196
+ // Generate helpers with custom naming conventions
197
+ const helpers = createPresetHelpers(name, config, {
198
+ featurePrefix: 'Manage',
199
+ widgetSuffix: 'Widget',
200
+ pageSuffix: 'Page'
201
+ });
202
+
203
+ return {
204
+ // Automatically scan folders in this preset directory
205
+ discoveryMode: 'auto',
206
+
207
+ // Expose helpers as variables to all templates
208
+ variables: {
209
+ ...helpers,
210
+ },
211
+
212
+ // enforce naming conventions for discovery
213
+ conventions: {
214
+ featureSlicePrefix: 'Manage',
215
+ widgetSliceSuffix: 'Widget',
216
+ pageSliceSuffix: 'Page'
217
+ },
218
+
219
+ // Configure automatic routing (e.g. for App.tsx injection)
220
+ routing: {
221
+ path: `/${name.toLowerCase()}`,
222
+ }
223
+ };
56
224
  });
57
225
  ```
58
226
 
227
+ **Available Variables (`GeneratorContext`) with Custom Config:**
228
+
229
+ Assuming input name is **"User"** and the configuration above:
230
+
231
+ | Variable | Description | Example Value |
232
+ | :--- | :--- | :--- |
233
+ | `base.name` | Original user input name | `User` |
234
+ | `layer.features.slice` | Feature slice name (prefix 'Manage') | `ManageUser` |
235
+ | `layer.features.importPath` | Feature import path | `@features/ManageUser` |
236
+ | `layer.widget.slice` | Widget slice name (suffix 'Widget') | `UserWidget` |
237
+ | `layer.widget.importPath` | Widget import path | `@widgets/UserWidget` |
238
+ | `layer.page.slice` | Page slice name (suffix 'Page') | `UserPage` |
239
+ | `layer.page.importPath` | Page import path | `@pages/UserPage` |
240
+
241
+
242
+
59
243
  ## License
60
244
 
61
245
  MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { readFileSync } from 'fs';
4
+ import { join, dirname } from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import { handleGenerate, handlePreset, handleReverseInit, handleReverseAnalyze, handleReverseBuild } from './lib/cli/handlers.js';
7
+ import { promptMainAction } from './lib/cli/prompts.js';
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ // In source, package.json is one level up from src/ (at the package root)
11
+ const pkgPath = join(__dirname, '..', 'package.json');
12
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
13
+ const program = new Command();
14
+ program
15
+ .name('fsd-gen')
16
+ .description(pkg.description || 'FSD Component Generator')
17
+ .version(pkg.version);
18
+ program
19
+ .command('generate')
20
+ .alias('g')
21
+ .description('Generate a new FSD slice or component')
22
+ .argument('[layer]', 'Layer (entity, feature, widget, page, shared)')
23
+ .argument('[slice]', 'Slice name (or path for shared)')
24
+ .argument('[name]', 'Component name (optional for some layers)')
25
+ .action(async (layer, slice, name) => {
26
+ try {
27
+ await handleGenerate(layer, slice, name);
28
+ }
29
+ catch (error) {
30
+ console.error(error.message || error);
31
+ process.exit(1);
32
+ }
33
+ });
34
+ program
35
+ .command('preset')
36
+ .argument('[presetName]', 'Name of the preset (e.g. table)')
37
+ .argument('[name]', 'Name of the entity/feature/etc')
38
+ .description('Generate a full vertical slice using a preset')
39
+ .action(async (presetName, name) => {
40
+ try {
41
+ await handlePreset(presetName, name);
42
+ }
43
+ catch (error) {
44
+ console.error(error.message || error);
45
+ process.exit(1);
46
+ }
47
+ });
48
+ program
49
+ .command('reverse:init')
50
+ .argument('[presetName]', 'Name of the new preset to initialize')
51
+ .option('-m, --mode <mode>', 'preset mode (short, ejected)', 'ejected')
52
+ .description('Initialize a workspace for reverse-engineering a preset')
53
+ .action(async (presetName, options) => {
54
+ try {
55
+ await handleReverseInit(presetName, options);
56
+ }
57
+ catch (error) {
58
+ console.error(error.message || error);
59
+ process.exit(1);
60
+ }
61
+ });
62
+ program
63
+ .command('reverse:analyze')
64
+ .argument('[presetName]', 'Name of the preset to analyze')
65
+ .description('Analyze the source code and generate a preset configuration')
66
+ .action(async (presetName) => {
67
+ try {
68
+ await handleReverseAnalyze(presetName);
69
+ }
70
+ catch (error) {
71
+ console.error(error.message || error);
72
+ process.exit(1);
73
+ }
74
+ });
75
+ program
76
+ .command('reverse:build')
77
+ .argument('[presetName]', 'Name of the preset to build')
78
+ .option('-m, --mode <mode>', 'preset mode (short, ejected)')
79
+ .description('Generate the final preset templates from configuration')
80
+ .action(async (presetName, options) => {
81
+ try {
82
+ await handleReverseBuild(presetName, options);
83
+ }
84
+ catch (error) {
85
+ console.error(error.message || error);
86
+ process.exit(1);
87
+ }
88
+ });
89
+ async function runInteractiveMenu() {
90
+ const action = await promptMainAction();
91
+ if (action === 'exit') {
92
+ process.exit(0);
93
+ }
94
+ // Pass the selected action as a command
95
+ program.parse(['node', 'cli.js', action]);
96
+ }
97
+ if (process.argv.length <= 2) {
98
+ runInteractiveMenu().catch((error) => {
99
+ console.error(error.message || error);
100
+ process.exit(1);
101
+ });
102
+ }
103
+ else {
104
+ program.parse();
105
+ }
@@ -1,4 +1,4 @@
1
- import { FsdGenConfig } from './types.js';
1
+ import type { FsdGenConfig } from './types.js';
2
2
  /**
3
3
  * Define configuration for fsd-gen.
4
4
  * @param config User configuration
@@ -1 +1 @@
1
- {"version":3,"file":"defineConfig.d.ts","sourceRoot":"","sources":["../../src/config/defineConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAE/D"}
1
+ {"version":3,"file":"defineConfig.d.ts","sourceRoot":"","sources":["../../src/config/defineConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAE/D"}
@@ -77,7 +77,7 @@ export interface PresetConfig {
77
77
  /** Optional discovery mode ('auto' = scan directories, 'manual' = use actions array) */
78
78
  discoveryMode?: (typeof DISCOVERY_MODES)[keyof typeof DISCOVERY_MODES];
79
79
  /** Global variables available in all templates */
80
- variables?: Record<string, string>;
80
+ variables?: Record<string, any>;
81
81
  /** Manual action definitions (required when discoveryMode is 'manual' or undefined) */
82
82
  actions?: PresetAction[];
83
83
  /** Convention overrides for auto-discovery mode */
@@ -95,4 +95,62 @@ export interface PresetConfigArgs {
95
95
  export type PresetConfigFn = (args: PresetConfigArgs) => PresetConfig;
96
96
  export declare function definePreset(config: PresetConfig): PresetConfig;
97
97
  export declare function definePreset(config: PresetConfigFn): PresetConfigFn;
98
+ export interface TemplateContext extends Record<string, any> {
99
+ componentName: string;
100
+ sliceName: string;
101
+ template: {
102
+ componentName: string;
103
+ sliceName: string;
104
+ layer: string;
105
+ };
106
+ }
107
+ export interface PresetHelpers {
108
+ base: {
109
+ /** Base name (same as input name) */
110
+ name: string;
111
+ /** Base name alias */
112
+ baseName: string;
113
+ };
114
+ layer: {
115
+ entity: {
116
+ /** Import path for entity layer (with or without alias) */
117
+ importPath: string;
118
+ /** Import path for entity API (usually /ui or /api) */
119
+ apiPath: string;
120
+ };
121
+ features: {
122
+ /** Feature slice name */
123
+ slice: string;
124
+ /** Import path for feature layer */
125
+ importPath: string;
126
+ };
127
+ widget: {
128
+ /** Widget slice name */
129
+ slice: string;
130
+ /** Import path for widget layer */
131
+ importPath: string;
132
+ };
133
+ page: {
134
+ /** Page slice name */
135
+ slice: string;
136
+ /** Import path for page layer */
137
+ importPath: string;
138
+ };
139
+ };
140
+ }
141
+ export interface PresetHelperOptions {
142
+ /** Prefix for feature slice names (default: 'Manage') */
143
+ featurePrefix?: string;
144
+ /** Suffix for widget slice names (default: 'Table') */
145
+ widgetSuffix?: string;
146
+ /** Suffix for page slice names (default: 'Page') */
147
+ pageSuffix?: string;
148
+ }
149
+ export interface GeneratorContext extends PresetHelpers, Record<string, any> {
150
+ template: {
151
+ componentName: string;
152
+ sliceName: string;
153
+ layer: string;
154
+ };
155
+ }
98
156
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { defineConfig } from './config/defineConfig.js';
2
- export { definePreset, type PresetConfig, type PresetConfigArgs, type PresetConfigFn, type FsdGenConfig, type ConventionConfig, type PresetAction } from './config/types.js';
3
- export { createPresetHelpers, type PresetHelpers, type PresetHelperOptions } from './lib/helpers/presetHelpers.js';
2
+ export { definePreset, type PresetConfig, type PresetConfigArgs, type PresetConfigFn, type FsdGenConfig, type ConventionConfig, type PresetAction, type TemplateContext, type PresetHelpers, type PresetHelperOptions, type GeneratorContext } from './config/types.js';
3
+ export { createPresetHelpers } from './lib/helpers/presetHelpers.js';
4
+ export type { PresetSourceConfig } from './lib/reverse/types.js';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC7K,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACxQ,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"updateBarrels.d.ts","sourceRoot":"","sources":["../../../src/lib/barrels/updateBarrels.ts"],"names":[],"mappings":"AAWA,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAqBrF"}
1
+ {"version":3,"file":"updateBarrels.d.ts","sourceRoot":"","sources":["../../../src/lib/barrels/updateBarrels.ts"],"names":[],"mappings":"AAWA,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAwBrF"}
@@ -16,10 +16,12 @@ export function updateBarrel(directory, exportName, exportPath) {
16
16
  }
17
17
  // Check if export already exists
18
18
  const exportStatement = `export * from './${exportPath}';`;
19
- // Or named export: export { Name } from './Path';
20
- // Spec says: "Автообновление barrel-файлов ... создаёт index.ts, добавляет export, не дублирует"
21
- // A simple heuristic: check if the string exists.
22
- if (content.includes(exportPath)) {
19
+ // Prevent index from exporting itself
20
+ if (exportPath === 'index') {
21
+ return;
22
+ }
23
+ // A more precise check for the exact export statement
24
+ if (content.includes(exportStatement)) {
23
25
  return;
24
26
  }
25
27
  const newContent = content + (content.endsWith('\n') || content === '' ? '' : '\n') + exportStatement + '\n';
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Handler for 'generate' command
3
+ */
4
+ export declare function handleGenerate(layer?: string, slice?: string, name?: string): Promise<void>;
5
+ /**
6
+ * Handler for 'preset' command
7
+ */
8
+ export declare function handlePreset(presetName?: string, name?: string): Promise<void>;
9
+ /**
10
+ * Handler for 'reverse:init' command
11
+ */
12
+ export declare function handleReverseInit(presetName?: string, options?: {
13
+ mode?: 'short' | 'ejected';
14
+ }): Promise<void>;
15
+ /**
16
+ * Handler for 'reverse:analyze' command
17
+ */
18
+ export declare function handleReverseAnalyze(presetName?: string): Promise<void>;
19
+ /**
20
+ * Handler for 'reverse:build' command
21
+ */
22
+ export declare function handleReverseBuild(presetName?: string, options?: {
23
+ mode?: 'short' | 'ejected';
24
+ }): Promise<void>;
25
+ //# sourceMappingURL=handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../../src/lib/cli/handlers.ts"],"names":[],"mappings":"AAoBA;;GAEG;AACH,wBAAsB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,iBAiCjF;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,iBAQpE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAO,iBAMxG;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,CAAC,EAAE,MAAM,iBAa7D;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAO,iBAazG"}
@@ -0,0 +1,97 @@
1
+ import { basename } from 'path';
2
+ import { loadConfig } from '../config/loadConfig.js';
3
+ import { validateConfig } from '../config/validateConfig.js';
4
+ import { resolveFsdPaths } from '../naming/resolvePaths.js';
5
+ import { toPascalCase } from '../naming/names.js';
6
+ import { generateComponent } from '../generators/generate.js';
7
+ import { createPresetHelpers } from '../helpers/presetHelpers.js';
8
+ import { generatePreset } from '../generators/generatePreset.js';
9
+ import { initReversePreset } from '../reverse/init.js';
10
+ import { analyzeReversePreset } from '../reverse/analyze.js';
11
+ import { buildReversePreset } from '../reverse/build.js';
12
+ import { listPresets } from '../templates/templateLoader.js';
13
+ import { promptLayer, promptSlice, promptPresetName, promptName } from './prompts.js';
14
+ /**
15
+ * Handler for 'generate' command
16
+ */
17
+ export async function handleGenerate(layer, slice, name) {
18
+ if (!layer)
19
+ layer = await promptLayer();
20
+ if (!slice)
21
+ slice = await promptSlice();
22
+ const finalLayer = layer;
23
+ const finalSlice = slice;
24
+ console.log('Loading configuration...');
25
+ const config = await loadConfig();
26
+ const validation = validateConfig(config);
27
+ if (!validation.valid) {
28
+ throw new Error(`Invalid configuration: ${validation.error}`);
29
+ }
30
+ if (!validation.config || !validation.config.rootDir) {
31
+ throw new Error('Invalid config: rootDir missing');
32
+ }
33
+ console.log(`Generating ${finalLayer}/${finalSlice}/${name || ''}...`);
34
+ const derivedName = name || basename(finalSlice);
35
+ const componentName = toPascalCase(derivedName);
36
+ const paths = resolveFsdPaths(validation.config.rootDir, finalLayer, finalSlice, componentName);
37
+ const helpers = createPresetHelpers(finalSlice, config);
38
+ await generateComponent(paths, {
39
+ ...helpers,
40
+ componentName,
41
+ sliceName: finalSlice,
42
+ layer: finalLayer,
43
+ template: { componentName, sliceName: finalSlice, layer: finalLayer }
44
+ });
45
+ }
46
+ /**
47
+ * Handler for 'preset' command
48
+ */
49
+ export async function handlePreset(presetName, name) {
50
+ const config = await loadConfig();
51
+ const templatesDir = config.templatesDir || 'templates';
52
+ if (!presetName)
53
+ presetName = await promptPresetName(templatesDir);
54
+ if (!name)
55
+ name = await promptName();
56
+ await generatePreset(presetName, name);
57
+ }
58
+ /**
59
+ * Handler for 'reverse:init' command
60
+ */
61
+ export async function handleReverseInit(presetName, options = {}) {
62
+ const config = await loadConfig();
63
+ const templatesDir = config.templatesDir || 'templates';
64
+ if (!presetName)
65
+ presetName = await promptName('Enter the name for the new preset:');
66
+ await initReversePreset(presetName, templatesDir, options.mode || 'ejected');
67
+ }
68
+ /**
69
+ * Handler for 'reverse:analyze' command
70
+ */
71
+ export async function handleReverseAnalyze(presetName) {
72
+ const config = await loadConfig();
73
+ const templatesDir = config.templatesDir || 'templates';
74
+ if (!presetName) {
75
+ const availablePresets = await listPresets(templatesDir);
76
+ if (availablePresets.length === 0) {
77
+ throw new Error('No presets found. Run "fsd-gen reverse:init <name>" first.');
78
+ }
79
+ presetName = await promptPresetName(templatesDir);
80
+ }
81
+ await analyzeReversePreset(presetName, templatesDir);
82
+ }
83
+ /**
84
+ * Handler for 'reverse:build' command
85
+ */
86
+ export async function handleReverseBuild(presetName, options = {}) {
87
+ const config = await loadConfig();
88
+ const templatesDir = config.templatesDir || 'templates';
89
+ if (!presetName) {
90
+ const availablePresets = await listPresets(templatesDir);
91
+ if (availablePresets.length === 0) {
92
+ throw new Error('No presets found.');
93
+ }
94
+ presetName = await promptPresetName(templatesDir);
95
+ }
96
+ await buildReversePreset(presetName, templatesDir, options.mode);
97
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Prompts the user to select an FSD layer
3
+ */
4
+ export declare function promptLayer(): Promise<string>;
5
+ /**
6
+ * Prompts the user to enter a slice name
7
+ */
8
+ export declare function promptSlice(): Promise<string>;
9
+ /**
10
+ * Prompts the user to select an available preset
11
+ */
12
+ export declare function promptPresetName(templatesDir?: string): Promise<string>;
13
+ /**
14
+ * Prompts the user to enter a name for a preset or entity
15
+ */
16
+ export declare function promptName(message?: string): Promise<string>;
17
+ /**
18
+ * Prompts for a general interactive action
19
+ */
20
+ export declare function promptMainAction(): Promise<string>;
21
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/lib/cli/prompts.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAUnD;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAUnD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW7E;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,OAAO,GAAE,MAAsC,GAAG,OAAO,CAAC,MAAM,CAAC,CAUjG;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAiBxD"}