@starodubenko/fsd-gen 0.1.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 (81) hide show
  1. package/README.md +61 -0
  2. package/cli.js +114 -0
  3. package/dist/config/defineConfig.d.ts +8 -0
  4. package/dist/config/defineConfig.d.ts.map +1 -0
  5. package/dist/config/defineConfig.js +8 -0
  6. package/dist/config/types.d.ts +98 -0
  7. package/dist/config/types.d.ts.map +1 -0
  8. package/dist/config/types.js +9 -0
  9. package/dist/index.d.ts +4 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +3 -0
  12. package/dist/lib/barrels/updateBarrels.d.ts +2 -0
  13. package/dist/lib/barrels/updateBarrels.d.ts.map +1 -0
  14. package/dist/lib/barrels/updateBarrels.js +28 -0
  15. package/dist/lib/config/loadConfig.d.ts +21 -0
  16. package/dist/lib/config/loadConfig.d.ts.map +1 -0
  17. package/dist/lib/config/loadConfig.js +61 -0
  18. package/dist/lib/config/validateConfig.d.ts +13 -0
  19. package/dist/lib/config/validateConfig.d.ts.map +1 -0
  20. package/dist/lib/config/validateConfig.js +19 -0
  21. package/dist/lib/constants.d.ts +113 -0
  22. package/dist/lib/constants.d.ts.map +1 -0
  23. package/dist/lib/constants.js +129 -0
  24. package/dist/lib/generators/generate.d.ts +45 -0
  25. package/dist/lib/generators/generate.d.ts.map +1 -0
  26. package/dist/lib/generators/generate.js +104 -0
  27. package/dist/lib/generators/generatePreset.d.ts +6 -0
  28. package/dist/lib/generators/generatePreset.d.ts.map +1 -0
  29. package/dist/lib/generators/generatePreset.js +102 -0
  30. package/dist/lib/helpers/presetHelpers.d.ts +55 -0
  31. package/dist/lib/helpers/presetHelpers.d.ts.map +1 -0
  32. package/dist/lib/helpers/presetHelpers.js +53 -0
  33. package/dist/lib/naming/names.d.ts +10 -0
  34. package/dist/lib/naming/names.d.ts.map +1 -0
  35. package/dist/lib/naming/names.js +15 -0
  36. package/dist/lib/naming/resolvePaths.d.ts +33 -0
  37. package/dist/lib/naming/resolvePaths.d.ts.map +1 -0
  38. package/dist/lib/naming/resolvePaths.js +58 -0
  39. package/dist/lib/preset/actionExecution.d.ts +32 -0
  40. package/dist/lib/preset/actionExecution.d.ts.map +1 -0
  41. package/dist/lib/preset/actionExecution.js +138 -0
  42. package/dist/lib/preset/presetDiscovery.d.ts +40 -0
  43. package/dist/lib/preset/presetDiscovery.d.ts.map +1 -0
  44. package/dist/lib/preset/presetDiscovery.js +189 -0
  45. package/dist/lib/preset/presetLoading.d.ts +22 -0
  46. package/dist/lib/preset/presetLoading.d.ts.map +1 -0
  47. package/dist/lib/preset/presetLoading.js +69 -0
  48. package/dist/lib/routing/injectRoute.d.ts +17 -0
  49. package/dist/lib/routing/injectRoute.d.ts.map +1 -0
  50. package/dist/lib/routing/injectRoute.js +66 -0
  51. package/dist/lib/templates/templateLoader.d.ts +31 -0
  52. package/dist/lib/templates/templateLoader.d.ts.map +1 -0
  53. package/dist/lib/templates/templateLoader.js +122 -0
  54. package/package.json +64 -0
  55. package/templates/entity/model-ui-basic/Component.styles.ts +1 -0
  56. package/templates/entity/model-ui-basic/Component.tsx +18 -0
  57. package/templates/feature/ui-model-basic/Component.styles.ts +1 -0
  58. package/templates/feature/ui-model-basic/Component.tsx +17 -0
  59. package/templates/page/ui-basic/Component.styles.ts +1 -0
  60. package/templates/page/ui-basic/Component.tsx +17 -0
  61. package/templates/preset/table/entity/api/create/Component.tsx +19 -0
  62. package/templates/preset/table/entity/api/delete/Component.tsx +17 -0
  63. package/templates/preset/table/entity/api/get/Component.tsx +34 -0
  64. package/templates/preset/table/entity/api/update/Component.tsx +18 -0
  65. package/templates/preset/table/entity/model.ts +9 -0
  66. package/templates/preset/table/entity/ui/Component.tsx +11 -0
  67. package/templates/preset/table/feature/buttons/create/Component.styles.ts +1 -0
  68. package/templates/preset/table/feature/buttons/create/Component.tsx +30 -0
  69. package/templates/preset/table/feature/buttons/delete/Component.styles.ts +1 -0
  70. package/templates/preset/table/feature/buttons/delete/Component.tsx +30 -0
  71. package/templates/preset/table/feature/buttons/edit/Component.styles.ts +1 -0
  72. package/templates/preset/table/feature/buttons/edit/Component.tsx +30 -0
  73. package/templates/preset/table/feature/buttons.tsx +11 -0
  74. package/templates/preset/table/page/page/Component.tsx +19 -0
  75. package/templates/preset/table/page/page.tsx +19 -0
  76. package/templates/preset/table/widget/table/Component.tsx +50 -0
  77. package/templates/preset/table/widget/table.tsx +50 -0
  78. package/templates/shared/ui-basic/Component.styles.ts +1 -0
  79. package/templates/shared/ui-basic/Component.tsx +18 -0
  80. package/templates/widget/ui-basic/Component.styles.ts +1 -0
  81. package/templates/widget/ui-basic/Component.tsx +18 -0
package/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # fsd-gen
2
+
3
+ A powerful CLI tool for scaffolding **Feature-Sliced Design (FSD)** components, slices, and layers. It automates boilerplate creation, manages dependencies, ensures consistent structure, and supports complex presets.
4
+
5
+ ## 🚀 Features
6
+
7
+ - **FSD Compliance**: Automatically generates correct folder structures.
8
+ - **Smart Presets**: Generate entire vertical slices with one command (e.g., `preset table`).
9
+ - **Path Resolution**: Built-in support for FSD aliases (`@entities`, `@features`, etc.).
10
+ - **Interactive Mode**: User-friendly prompts for missing arguments.
11
+ - **Customizable**: `fsdgen.config.ts` for project-specific settings.
12
+
13
+ ## 📦 Installation
14
+
15
+ ```bash
16
+ npm install -D @starodubenko/fsd-gen
17
+ ```
18
+
19
+ ## 🛠 Usage
20
+
21
+ ### Basic Component Generation
22
+
23
+ ```bash
24
+ npx @starodubenko/fsd-gen generate <layer> <slice> [name]
25
+ ```
26
+
27
+ **Example:**
28
+ ```bash
29
+ npx @starodubenko/fsd-gen generate entity User UserCard
30
+ ```
31
+
32
+ ### Using Presets
33
+
34
+ Presets generate multiple related components across layers.
35
+
36
+ ```bash
37
+ npx @starodubenko/fsd-gen preset table Product
38
+ ```
39
+
40
+ ## ⚙️ Configuration
41
+
42
+ Create an `fsdgen.config.ts` in your project root:
43
+
44
+ ```typescript
45
+ import { defineConfig } from '@starodubenko/fsd-gen';
46
+
47
+ export default defineConfig({
48
+ rootDir: 'src',
49
+ aliases: {
50
+ '@entities': './src/entities',
51
+ '@features': './src/features',
52
+ '@widgets': './src/widgets',
53
+ '@pages': './src/pages',
54
+ '@shared': './src/shared',
55
+ }
56
+ });
57
+ ```
58
+
59
+ ## License
60
+
61
+ MIT
package/cli.js ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import { readFileSync } from 'fs';
5
+ import { join, dirname } from 'path';
6
+ import { fileURLToPath } from 'url';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+
11
+ const pkg = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf-8'));
12
+
13
+ const program = new Command();
14
+
15
+ program
16
+ .name('fsd-gen')
17
+ .description(pkg.description || 'FSD Component Generator')
18
+ .version(pkg.version);
19
+
20
+ program
21
+ .command('generate')
22
+ .alias('g')
23
+ .description('Generate a new FSD slice or component')
24
+ .argument('<layer>', 'Layer (entity, feature, widget, page, shared)')
25
+ .argument('<slice>', 'Slice name (or path for shared)')
26
+ .argument('[name]', 'Component name (optional for some layers)')
27
+ .action(async (layer, slice, name) => {
28
+ const { loadConfig } = await import('./dist/lib/config/loadConfig.js');
29
+ const { validateConfig } = await import('./dist/lib/config/validateConfig.js');
30
+
31
+ console.log('Loading configuration...');
32
+ const config = await loadConfig();
33
+
34
+ const validation = validateConfig(config);
35
+ if (!validation.valid) {
36
+ console.error('Invalid configuration:', validation.error);
37
+ process.exit(1);
38
+ }
39
+
40
+ console.log(`Generating ${layer}/${slice}/${name || ''}...`);
41
+
42
+ const { resolveFsdPaths } = await import('./dist/lib/naming/resolvePaths.js');
43
+ const { toPascalCase } = await import('./dist/lib/naming/names.js');
44
+ const { basename } = await import('path');
45
+
46
+ // If name is provided, use it.
47
+ // If not, derive from slice.
48
+ // If slice contains slashes (e.g. shared/ui/Button), take basename (Button).
49
+ const derivedName = name || basename(slice);
50
+ const componentName = toPascalCase(derivedName);
51
+
52
+ if (!validation.config || !validation.config.rootDir) {
53
+ throw new Error('Invalid config: rootDir missing');
54
+ }
55
+
56
+ const paths = resolveFsdPaths(validation.config.rootDir, layer, slice, componentName);
57
+
58
+ console.log('Paths:', JSON.stringify(paths, null, 2));
59
+
60
+ const { generateComponent } = await import('./dist/lib/generators/generate.js');
61
+ await generateComponent(paths, { componentName, sliceName: slice, layer });
62
+ });
63
+
64
+ program
65
+ .command('preset')
66
+ .argument('[presetName]', 'Name of the preset (e.g. table)')
67
+ .argument('[name]', 'Name of the entity/feature/etc')
68
+ .description('Generate a full vertical slice using a preset')
69
+ .action(async (presetName, name) => {
70
+ try {
71
+ // Load config to get templatesDir
72
+ const { loadConfig } = await import('./dist/lib/config/loadConfig.js');
73
+ const config = await loadConfig();
74
+
75
+ if (!presetName || !name) {
76
+ const inquirer = (await import('inquirer')).default;
77
+ const { listPresets } = await import('./dist/lib/templates/templateLoader.js');
78
+
79
+ const availablePresets = await listPresets(config.templatesDir);
80
+
81
+ const questions = [];
82
+
83
+ if (!presetName) {
84
+ questions.push({
85
+ type: 'list',
86
+ name: 'presetName',
87
+ message: 'Select a preset:',
88
+ choices: availablePresets.length > 0 ? availablePresets : ['table']
89
+ });
90
+ }
91
+
92
+ if (!name) {
93
+ questions.push({
94
+ type: 'input',
95
+ name: 'name',
96
+ message: 'Enter the name (e.g. User):',
97
+ validate: input => input ? true : 'Name is required'
98
+ });
99
+ }
100
+
101
+ const answers = await inquirer.prompt(questions);
102
+ presetName = presetName || answers.presetName;
103
+ name = name || answers.name;
104
+ }
105
+
106
+ const { generatePreset } = await import('./dist/lib/generators/generatePreset.js');
107
+ await generatePreset(presetName, name);
108
+ } catch (error) {
109
+ console.error('Preset generation failed:', error);
110
+ process.exit(1);
111
+ }
112
+ });
113
+
114
+ program.parse();
@@ -0,0 +1,8 @@
1
+ import { FsdGenConfig } from './types.js';
2
+ /**
3
+ * Define configuration for fsd-gen.
4
+ * @param config User configuration
5
+ * @returns User configuration
6
+ */
7
+ export declare function defineConfig(config: FsdGenConfig): FsdGenConfig;
8
+ //# sourceMappingURL=defineConfig.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Define configuration for fsd-gen.
3
+ * @param config User configuration
4
+ * @returns User configuration
5
+ */
6
+ export function defineConfig(config) {
7
+ return config;
8
+ }
@@ -0,0 +1,98 @@
1
+ import { FSD_LAYERS, NAMING_MODES, ACTION_TYPES, DISCOVERY_MODES } from '../lib/constants.js';
2
+ export type Layer = (typeof FSD_LAYERS)[keyof typeof FSD_LAYERS];
3
+ export interface FsdGenConfig {
4
+ /**
5
+ * Root directory of the source code.
6
+ * @default "src"
7
+ */
8
+ rootDir?: string;
9
+ /**
10
+ * Alias configuration.
11
+ * Key is the alias (e.g., "@"), value is the path relative to root (e.g., "./src").
12
+ */
13
+ aliases?: Record<string, string>;
14
+ /**
15
+ * Directory containing custom templates.
16
+ * Calculated relative to the config file or process.cwd().
17
+ */
18
+ templatesDir?: string;
19
+ /**
20
+ * Naming convention enforcement.
21
+ * @default "warn"
22
+ */
23
+ naming?: (typeof NAMING_MODES)[keyof typeof NAMING_MODES];
24
+ }
25
+ export declare const defaultConfig: FsdGenConfig;
26
+ export type PresetActionType = (typeof ACTION_TYPES)[keyof typeof ACTION_TYPES];
27
+ export interface PresetActionBase {
28
+ type: PresetActionType;
29
+ variables?: Record<string, string>;
30
+ }
31
+ export interface PresetComponentAction extends PresetActionBase {
32
+ type: typeof ACTION_TYPES.COMPONENT;
33
+ layer: Layer;
34
+ slice: string;
35
+ name?: string;
36
+ template: string;
37
+ }
38
+ export interface PresetFileAction extends PresetActionBase {
39
+ type: typeof ACTION_TYPES.FILE;
40
+ path: string;
41
+ template: string;
42
+ }
43
+ export interface PresetHookAction extends PresetActionBase {
44
+ type: typeof ACTION_TYPES.HOOK;
45
+ layer: Layer;
46
+ slice: string;
47
+ name?: string;
48
+ template: string;
49
+ }
50
+ export interface PresetStylesAction extends PresetActionBase {
51
+ type: typeof ACTION_TYPES.STYLES;
52
+ layer: Layer;
53
+ slice: string;
54
+ name?: string;
55
+ template: string;
56
+ }
57
+ export type PresetAction = PresetComponentAction | PresetFileAction | PresetHookAction | PresetStylesAction;
58
+ export interface ConventionConfig {
59
+ /** Prefix for feature slice names (e.g., 'Manage' -> 'ManageUser') */
60
+ featureSlicePrefix?: string;
61
+ /** Suffix for widget slice names (e.g., 'Table' -> 'UserTable') */
62
+ widgetSliceSuffix?: string;
63
+ /** Suffix for page slice names (e.g., 'Page' -> 'UserPage') */
64
+ pageSliceSuffix?: string;
65
+ }
66
+ export interface RouteConfig {
67
+ /** Route path (e.g., '/users', '/products/:id') */
68
+ path: string;
69
+ /** Import path for the page component (will be auto-generated if not provided) */
70
+ importPath?: string;
71
+ /** Component name (will be auto-generated from entity name if not provided) */
72
+ componentName?: string;
73
+ /** Target file for route injection (e.g., 'Router.tsx') @default "App.tsx" */
74
+ appFile?: string;
75
+ }
76
+ export interface PresetConfig {
77
+ /** Optional discovery mode ('auto' = scan directories, 'manual' = use actions array) */
78
+ discoveryMode?: (typeof DISCOVERY_MODES)[keyof typeof DISCOVERY_MODES];
79
+ /** Global variables available in all templates */
80
+ variables?: Record<string, string>;
81
+ /** Manual action definitions (required when discoveryMode is 'manual' or undefined) */
82
+ actions?: PresetAction[];
83
+ /** Convention overrides for auto-discovery mode */
84
+ conventions?: ConventionConfig;
85
+ /** Route configuration for automatic route generation */
86
+ routing?: RouteConfig;
87
+ }
88
+ /** Arguments passed to preset configuration function */
89
+ export interface PresetConfigArgs {
90
+ /** The entity name provided by the user (e.g., 'User', 'Product') */
91
+ name: string;
92
+ /** The loaded FSD generator configuration */
93
+ config: FsdGenConfig;
94
+ }
95
+ export type PresetConfigFn = (args: PresetConfigArgs) => PresetConfig;
96
+ export declare function definePreset(config: PresetConfig): PresetConfig;
97
+ export declare function definePreset(config: PresetConfigFn): PresetConfigFn;
98
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAoB,MAAM,qBAAqB,CAAC;AAEhH,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAEjE,MAAM,WAAW,YAAY;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;CAC7D;AAED,eAAO,MAAM,aAAa,EAAE,YAI3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAEhF,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,gBAAgB,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC3D,IAAI,EAAE,OAAO,YAAY,CAAC,SAAS,CAAC;IACpC,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAiB,SAAQ,gBAAgB;IACtD,IAAI,EAAE,OAAO,YAAY,CAAC,IAAI,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAiB,SAAQ,gBAAgB;IACtD,IAAI,EAAE,OAAO,YAAY,CAAC,IAAI,CAAC;IAC/B,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IACxD,IAAI,EAAE,OAAO,YAAY,CAAC,MAAM,CAAC;IACjC,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,YAAY,GAAG,qBAAqB,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,kBAAkB,CAAC;AAE5G,MAAM,WAAW,gBAAgB;IAC7B,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,+DAA+D;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IACxB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IACzB,wFAAwF;IACxF,aAAa,CAAC,EAAE,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;IACvE,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,uFAAuF;IACvF,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,mDAAmD;IACnD,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,yDAAyD;IACzD,OAAO,CAAC,EAAE,WAAW,CAAC;CACzB;AAED,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC7B,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,MAAM,EAAE,YAAY,CAAC;CACxB;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,gBAAgB,KAAK,YAAY,CAAC;AAGtE,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAAC;AACjE,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { NAMING_MODES, DEFAULT_ROOT_DIR } from '../lib/constants.js';
2
+ export const defaultConfig = {
3
+ rootDir: DEFAULT_ROOT_DIR,
4
+ aliases: { '@': './src' },
5
+ naming: NAMING_MODES.WARN,
6
+ };
7
+ export function definePreset(config) {
8
+ return config;
9
+ }
@@ -0,0 +1,4 @@
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';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { defineConfig } from './config/defineConfig.js';
2
+ export { definePreset } from './config/types.js';
3
+ export { createPresetHelpers } from './lib/helpers/presetHelpers.js';
@@ -0,0 +1,2 @@
1
+ export declare function updateBarrel(directory: string, exportName: string, exportPath: string): void;
2
+ //# sourceMappingURL=updateBarrels.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Utility functions for updating barrel (index.ts) files.
3
+ *
4
+ * Ensures that newly generated slices, segments, or components are automatically
5
+ * exported from their parent directories, maintaining clean import paths compliant
6
+ * with Feature-Sliced Design public API capability.
7
+ */
8
+ import { join } from 'path';
9
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
10
+ import { FILE_EXTENSIONS } from '../constants.js';
11
+ export function updateBarrel(directory, exportName, exportPath) {
12
+ const indexFile = join(directory, FILE_EXTENSIONS.INDEX);
13
+ let content = '';
14
+ if (existsSync(indexFile)) {
15
+ content = readFileSync(indexFile, 'utf-8');
16
+ }
17
+ // Check if export already exists
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)) {
23
+ return;
24
+ }
25
+ const newContent = content + (content.endsWith('\n') || content === '' ? '' : '\n') + exportStatement + '\n';
26
+ writeFileSync(indexFile, newContent);
27
+ console.log(`Updated ${indexFile}`);
28
+ }
@@ -0,0 +1,21 @@
1
+ import { FsdGenConfig } from '../../config/types.js';
2
+ /**
3
+ * Find the config file in the given directory
4
+ * @returns The config file path or null if not found
5
+ */
6
+ export declare function findConfigFile(cwd: string): string | null;
7
+ /**
8
+ * Read and parse the config file
9
+ * @returns The parsed config object
10
+ */
11
+ export declare function readConfigFile(configPath: string): Promise<Partial<FsdGenConfig>>;
12
+ /**
13
+ * Merge user config with default config
14
+ */
15
+ export declare function mergeWithDefaults(config: Partial<FsdGenConfig>): FsdGenConfig;
16
+ /**
17
+ * Load the FSD generator configuration
18
+ * Orchestrates finding, reading, and merging config
19
+ */
20
+ export declare function loadConfig(cwd?: string): Promise<FsdGenConfig>;
21
+ //# sourceMappingURL=loadConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadConfig.d.ts","sourceRoot":"","sources":["../../../src/lib/config/loadConfig.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAiB,MAAM,uBAAuB,CAAC;AAGpE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGzD;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CASvF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAK7E;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,YAAY,CAAC,CAcnF"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Configuration loading logic.
3
+ *
4
+ * Responsible for finding, reading, parsing, and merging the fsd-gen configuration
5
+ * file (fsdgen.config.ts/js). Handles JIT compilation of TypeScript configs.
6
+ */
7
+ import { join } from 'path';
8
+ import { existsSync } from 'fs';
9
+ import { createJiti } from 'jiti';
10
+ import { defaultConfig } from '../../config/types.js';
11
+ import { CONFIG_FILES } from '../constants.js';
12
+ /**
13
+ * Find the config file in the given directory
14
+ * @returns The config file path or null if not found
15
+ */
16
+ export function findConfigFile(cwd) {
17
+ const configPath = join(cwd, CONFIG_FILES.FSD_GEN);
18
+ return existsSync(configPath) ? configPath : null;
19
+ }
20
+ /**
21
+ * Read and parse the config file
22
+ * @returns The parsed config object
23
+ */
24
+ export async function readConfigFile(configPath) {
25
+ try {
26
+ const jiti = createJiti(import.meta.url);
27
+ const imported = await jiti.import(configPath, { default: true });
28
+ return imported;
29
+ }
30
+ catch (error) {
31
+ console.error('Failed to load config:', error);
32
+ throw error;
33
+ }
34
+ }
35
+ /**
36
+ * Merge user config with default config
37
+ */
38
+ export function mergeWithDefaults(config) {
39
+ return {
40
+ ...defaultConfig,
41
+ ...config,
42
+ };
43
+ }
44
+ /**
45
+ * Load the FSD generator configuration
46
+ * Orchestrates finding, reading, and merging config
47
+ */
48
+ export async function loadConfig(cwd = process.cwd()) {
49
+ const configPath = findConfigFile(cwd);
50
+ if (!configPath) {
51
+ return defaultConfig;
52
+ }
53
+ try {
54
+ const userConfig = await readConfigFile(configPath);
55
+ return mergeWithDefaults(userConfig);
56
+ }
57
+ catch {
58
+ console.error('Failed to load config, using defaults');
59
+ return defaultConfig;
60
+ }
61
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Configuration validation logic.
3
+ *
4
+ * Uses Zod schemas to ensure the loaded configuration meets the required
5
+ * structure and constraints before the generator proceeds.
6
+ */
7
+ import { FsdGenConfig } from '../../config/types.js';
8
+ export declare function validateConfig(config: unknown): {
9
+ valid: boolean;
10
+ error?: string;
11
+ config?: FsdGenConfig;
12
+ };
13
+ //# sourceMappingURL=validateConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateConfig.d.ts","sourceRoot":"","sources":["../../../src/lib/config/validateConfig.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AASrD,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,YAAY,CAAA;CAAE,CAczG"}
@@ -0,0 +1,19 @@
1
+ import { z } from 'zod';
2
+ const configSchema = z.object({
3
+ rootDir: z.string().optional(),
4
+ aliases: z.record(z.string(), z.string()).optional(),
5
+ naming: z.enum(['error', 'warn', 'autoFix']).optional(),
6
+ });
7
+ export function validateConfig(config) {
8
+ const result = configSchema.safeParse(config);
9
+ if (!result.success) {
10
+ return {
11
+ valid: false,
12
+ error: result.error.message
13
+ };
14
+ }
15
+ return {
16
+ valid: true,
17
+ config: result.data
18
+ };
19
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * FSD Layer names and their plural forms
3
+ */
4
+ export declare const FSD_LAYERS: {
5
+ readonly ENTITY: "entity";
6
+ readonly FEATURE: "feature";
7
+ readonly WIDGET: "widget";
8
+ readonly PAGE: "page";
9
+ readonly SHARED: "shared";
10
+ };
11
+ export declare const LAYER_PLURALS: Record<string, string>;
12
+ /**
13
+ * FSD segment names (directories within slices)
14
+ */
15
+ export declare const FSD_SEGMENTS: {
16
+ readonly UI: "ui";
17
+ readonly MODEL: "model";
18
+ readonly API: "api";
19
+ readonly LIB: "lib";
20
+ readonly CONFIG: "config";
21
+ };
22
+ /**
23
+ * Template types for different layers
24
+ */
25
+ export declare const DEFAULT_TEMPLATES: Record<string, string>;
26
+ /**
27
+ * File extensions
28
+ */
29
+ export declare const FILE_EXTENSIONS: {
30
+ readonly TYPESCRIPT: ".ts";
31
+ readonly TSX: ".tsx";
32
+ readonly STYLES: ".styles.ts";
33
+ readonly JSON: ".json";
34
+ readonly CONFIG: "config.ts";
35
+ readonly INDEX: "index.ts";
36
+ };
37
+ /**
38
+ * Configuration file names
39
+ */
40
+ export declare const CONFIG_FILES: {
41
+ readonly FSD_GEN: "fsdgen.config.ts";
42
+ readonly PRESET_TS: "preset.ts";
43
+ readonly PRESET_JSON: "preset.json";
44
+ };
45
+ /**
46
+ * Preset directory names
47
+ */
48
+ export declare const PRESET_DIRS: {
49
+ readonly ROOT: "preset";
50
+ readonly BUTTONS: "buttons";
51
+ readonly TABLE: "table";
52
+ };
53
+ /**
54
+ * API hook operation names
55
+ */
56
+ export declare const API_OPERATIONS: {
57
+ readonly GET: "get";
58
+ readonly CREATE: "create";
59
+ readonly UPDATE: "update";
60
+ readonly DELETE: "delete";
61
+ };
62
+ /**
63
+ * API hook name prefixes
64
+ */
65
+ export declare const API_HOOK_PREFIXES: Record<string, string>;
66
+ /**
67
+ * Default fallback template
68
+ */
69
+ export declare const DEFAULT_TEMPLATE = "ui-basic";
70
+ /**
71
+ * Default root directory
72
+ */
73
+ export declare const DEFAULT_ROOT_DIR = "src";
74
+ /**
75
+ * Preset action types
76
+ */
77
+ export declare const ACTION_TYPES: {
78
+ readonly COMPONENT: "component";
79
+ readonly FILE: "file";
80
+ readonly HOOK: "hook";
81
+ readonly STYLES: "styles";
82
+ };
83
+ /**
84
+ * Discovery modes
85
+ */
86
+ export declare const DISCOVERY_MODES: {
87
+ readonly AUTO: "auto";
88
+ readonly MANUAL: "manual";
89
+ };
90
+ /**
91
+ * Naming convention modes
92
+ */
93
+ export declare const NAMING_MODES: {
94
+ readonly ERROR: "error";
95
+ readonly WARN: "warn";
96
+ readonly AUTO_FIX: "autoFix";
97
+ };
98
+ /**
99
+ * Routing configuration constants
100
+ */
101
+ export declare const ROUTING: {
102
+ readonly MARKER: "{/* ROUTES_INJECTION_POINT */}";
103
+ readonly IMPORTS_REGEX: RegExp;
104
+ readonly APP_FILE: "App.tsx";
105
+ };
106
+ /**
107
+ * Template file names
108
+ */
109
+ export declare const TEMPLATE_FILES: {
110
+ readonly COMPONENT: "Component.tsx";
111
+ readonly STYLES: "Component.styles.ts";
112
+ };
113
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;CAMb,CAAC;AAEX,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMhD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;;CAMf,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;CAOlB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,WAAW;;;;CAId,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,cAAc;;;;;CAKjB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,aAAa,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,gBAAgB,QAAQ,CAAC;AAEtC;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;CAKf,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,eAAe;;;CAGlB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,OAAO;;;;CAIV,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,cAAc;;;CAGjB,CAAC"}