@xanahlight/component-forge 0.1.0 → 1.5.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 (55) hide show
  1. package/README.md +8 -0
  2. package/dist/commands/check/index.d.ts +30 -0
  3. package/dist/commands/check/index.js +255 -0
  4. package/dist/commands/check/index.js.map +1 -0
  5. package/dist/commands/explain/index.d.ts +12 -0
  6. package/dist/commands/explain/index.js +37 -0
  7. package/dist/commands/explain/index.js.map +1 -0
  8. package/dist/commands/explain/topics.d.ts +3 -0
  9. package/dist/commands/explain/topics.js +138 -0
  10. package/dist/commands/explain/topics.js.map +1 -0
  11. package/dist/commands/{generate.d.ts → generate/index.d.ts} +1 -1
  12. package/dist/commands/{generate.js → generate/index.js} +21 -12
  13. package/dist/commands/generate/index.js.map +1 -0
  14. package/dist/commands/init/index.d.ts +29 -0
  15. package/dist/commands/init/index.js +157 -0
  16. package/dist/commands/init/index.js.map +1 -0
  17. package/dist/commands/migrate/classifier.d.ts +22 -0
  18. package/dist/commands/migrate/classifier.js +48 -0
  19. package/dist/commands/migrate/classifier.js.map +1 -0
  20. package/dist/commands/migrate/index.d.ts +8 -0
  21. package/dist/commands/migrate/index.js +33 -0
  22. package/dist/commands/migrate/index.js.map +1 -0
  23. package/dist/commands/migrate/plan-builder.d.ts +27 -0
  24. package/dist/commands/migrate/plan-builder.js +106 -0
  25. package/dist/commands/migrate/plan-builder.js.map +1 -0
  26. package/dist/commands/migrate/printer.d.ts +6 -0
  27. package/dist/commands/migrate/printer.js +46 -0
  28. package/dist/commands/migrate/printer.js.map +1 -0
  29. package/dist/commands/validate/index.d.ts +26 -0
  30. package/dist/commands/{validate.js → validate/index.js} +8 -5
  31. package/dist/commands/validate/index.js.map +1 -0
  32. package/dist/index.js +106 -10
  33. package/dist/index.js.map +1 -1
  34. package/dist/shared/format.d.ts +26 -0
  35. package/dist/shared/format.js +40 -0
  36. package/dist/shared/format.js.map +1 -0
  37. package/dist/templates/files.d.ts +1 -1
  38. package/dist/templates/files.js +61 -9
  39. package/dist/templates/files.js.map +1 -1
  40. package/dist/types/folder-tree.d.ts +31 -2
  41. package/dist/types/folder-tree.js +18 -0
  42. package/dist/types/folder-tree.js.map +1 -1
  43. package/dist/utils/config.d.ts +19 -6
  44. package/dist/utils/config.js +76 -14
  45. package/dist/utils/config.js.map +1 -1
  46. package/dist/utils/template-resolver.d.ts +1 -1
  47. package/dist/utils/template-resolver.js +1 -1
  48. package/dist/utils/template-resolver.js.map +1 -1
  49. package/package.json +14 -6
  50. package/dist/commands/generate.js.map +0 -1
  51. package/dist/commands/init.d.ts +0 -10
  52. package/dist/commands/init.js +0 -54
  53. package/dist/commands/init.js.map +0 -1
  54. package/dist/commands/validate.d.ts +0 -1
  55. package/dist/commands/validate.js.map +0 -1
package/dist/index.js CHANGED
@@ -2,26 +2,37 @@
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const commander_1 = require("commander");
5
- const init_1 = require("./commands/init");
5
+ const check_1 = require("./commands/check");
6
+ const explain_1 = require("./commands/explain");
6
7
  const generate_1 = require("./commands/generate");
8
+ const init_1 = require("./commands/init");
9
+ const migrate_1 = require("./commands/migrate");
7
10
  const validate_1 = require("./commands/validate");
11
+ // Read version from package.json at runtime — stays in sync automatically.
12
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
13
+ const { version } = require('../package.json');
8
14
  const program = new commander_1.Command();
9
15
  program
10
16
  .name('component-forge')
11
17
  .description('Architecture-first CLI for scalable React projects')
12
- .version('0.1.0');
18
+ .version(version);
19
+ // ---------------------------------------------------------------------------
20
+ // init
21
+ // ---------------------------------------------------------------------------
13
22
  program
14
23
  .command('init')
15
- .description('Initialize project structure')
16
- .argument('<architecture>', 'Architecture type (fsd | modular)', (value) => {
17
- if (!['fsd', 'modular'].includes(value)) {
18
- throw new Error('Architecture must be fsd or modular');
19
- }
20
- return value;
21
- })
24
+ .description('Initialize project structure (interactive if no architecture provided)')
25
+ .argument('[architecture]', 'Architecture type: fsd | modular (optional prompts if omitted)')
22
26
  .action((architecture) => {
27
+ if (architecture !== undefined && !['fsd', 'modular'].includes(architecture)) {
28
+ console.error(`error: architecture must be "fsd" or "modular", got "${architecture}"`);
29
+ process.exit(1);
30
+ }
23
31
  (0, init_1.initCommand)(architecture);
24
32
  });
33
+ // ---------------------------------------------------------------------------
34
+ // generate
35
+ // ---------------------------------------------------------------------------
25
36
  const SLICE_TYPES = ['feature', 'entity', 'widget', 'page', 'component', 'module'];
26
37
  program
27
38
  .command('generate')
@@ -33,16 +44,101 @@ program
33
44
  }
34
45
  return value;
35
46
  })
36
- .argument('<name>', 'Slice name')
47
+ .argument('<name>', 'Slice name — supports nested paths (e.g. auth/LoginForm) to place the slice inside a subfolder')
37
48
  .option('--dry-run', 'Preview files that would be generated without writing them')
49
+ .addHelpText('after', `
50
+ Slice types and their generated structure:
51
+ feature Full vertical slice → ui/<Name>.tsx model/index.ts api/index.ts index.ts
52
+ entity Data-layer slice → model/index.ts api/index.ts index.ts
53
+ widget Composite UI block → ui/<Name>.tsx model/index.ts index.ts
54
+ page Route-level shell → ui/<Name>Page.tsx index.ts
55
+ component Pure UI atom → <Name>.tsx index.ts
56
+ module Vertical module → ui/<Name>.tsx model/index.ts api/index.ts index.ts
57
+
58
+ Nested paths:
59
+ The <name> argument supports "/" separators to nest the slice inside a subdirectory.
60
+ The basename is used for the component name in generated files.
61
+
62
+ Examples:
63
+ $ component-forge g feature auth
64
+ Creates: src/features/auth/
65
+
66
+ $ component-forge g feature auth/LoginForm
67
+ Creates: src/features/auth/LoginForm/ (component name: LoginForm)
68
+
69
+ $ component-forge g entity user/profile/Address
70
+ Creates: src/entities/user/profile/Address/ (component name: Address)
71
+
72
+ $ component-forge g component Button --dry-run
73
+ Preview: src/shared/ui/Button/
74
+ `)
38
75
  .action((type, name, options) => {
39
76
  (0, generate_1.generateCommand)(type, name, { dryRun: options.dryRun });
40
77
  });
78
+ // ---------------------------------------------------------------------------
79
+ // validate
80
+ // ---------------------------------------------------------------------------
41
81
  program
42
82
  .command('validate')
43
83
  .description('Validate project structure against the configured architecture')
44
84
  .action(() => {
45
85
  (0, validate_1.validateCommand)();
46
86
  });
87
+ // ---------------------------------------------------------------------------
88
+ // check
89
+ // ---------------------------------------------------------------------------
90
+ program
91
+ .command('check')
92
+ .description('Check that imports do not violate architecture layer boundaries')
93
+ .addHelpText('after', `
94
+ Each violation is printed with a targeted "→ Fix:" hint.
95
+ Exits with code 1 when violations are found (useful in CI pipelines).
96
+
97
+ Example:
98
+ $ component-forge check
99
+ `)
100
+ .action(() => {
101
+ (0, check_1.checkCommand)();
102
+ });
103
+ // ---------------------------------------------------------------------------
104
+ // migrate
105
+ // ---------------------------------------------------------------------------
106
+ program
107
+ .command('migrate')
108
+ .description('Analyse current project structure and propose a migration plan')
109
+ .requiredOption('--to <architecture>', 'Target architecture: fsd | modular')
110
+ .addHelpText('after', `
111
+ Scans your source directory and prints a step-by-step migration plan.
112
+ No files are moved — this is a dry-run analysis only.
113
+
114
+ Examples:
115
+ $ component-forge migrate --to fsd
116
+ $ component-forge migrate --to modular
117
+ `)
118
+ .action((options) => {
119
+ if (!['fsd', 'modular'].includes(options.to)) {
120
+ console.error(`error: --to must be "fsd" or "modular", got "${options.to}"`);
121
+ process.exit(1);
122
+ }
123
+ (0, migrate_1.migrateCommand)(options.to);
124
+ });
125
+ // ---------------------------------------------------------------------------
126
+ // explain
127
+ // ---------------------------------------------------------------------------
128
+ program
129
+ .command('explain')
130
+ .description('Print architecture documentation in the terminal')
131
+ .argument('<topic>', `Topic to explain: ${explain_1.AVAILABLE_TOPICS.join(' | ')}`)
132
+ .addHelpText('after', `
133
+ Available topics: fsd, modular, layers, slices, segments
134
+
135
+ Examples:
136
+ $ component-forge explain fsd
137
+ $ component-forge explain layers
138
+ $ component-forge explain slices
139
+ `)
140
+ .action((topic) => {
141
+ (0, explain_1.explainCommand)(topic);
142
+ });
47
143
  program.parse(process.argv);
48
144
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yCAAmC;AAEnC,0CAA6C;AAC7C,kDAAgE;AAChE,kDAAqD;AAErD,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAA;AAE7B,OAAO;KACJ,IAAI,CAAC,iBAAiB,CAAC;KACvB,WAAW,CAAC,oDAAoD,CAAC;KACjE,OAAO,CAAC,OAAO,CAAC,CAAA;AAEnB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,8BAA8B,CAAC;KAC3C,QAAQ,CAAC,gBAAgB,EAAE,mCAAmC,EAAE,CAAC,KAAK,EAAE,EAAE;IACzE,IAAI,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IACxD,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAC;KACD,MAAM,CAAC,CAAC,YAA+B,EAAE,EAAE;IAC1C,IAAA,kBAAW,EAAC,YAAY,CAAC,CAAA;AAC3B,CAAC,CAAC,CAAA;AAEJ,MAAM,WAAW,GAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAA;AAE/F,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,KAAK,CAAC,GAAG,CAAC;KACV,WAAW,CAAC,+BAA+B,CAAC;KAC5C,QAAQ,CAAC,QAAQ,EAAE,eAAe,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;IACvE,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAkB,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,wBAAwB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACnE,CAAC;IACD,OAAO,KAAkB,CAAA;AAC3B,CAAC,CAAC;KACD,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;KAChC,MAAM,CAAC,WAAW,EAAE,4DAA4D,CAAC;KACjF,MAAM,CAAC,CAAC,IAAe,EAAE,IAAY,EAAE,OAA6B,EAAE,EAAE;IACvE,IAAA,0BAAe,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;AACzD,CAAC,CAAC,CAAA;AAEJ,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,gEAAgE,CAAC;KAC7E,MAAM,CAAC,GAAG,EAAE;IACX,IAAA,0BAAe,GAAE,CAAA;AACnB,CAAC,CAAC,CAAA;AAEJ,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export declare const fmt: {
2
+ /** Bold white section heading */
3
+ readonly h1: (text: string) => string;
4
+ /** Bold cyan sub-heading */
5
+ readonly h2: (text: string) => string;
6
+ /** Dim horizontal rule (58 chars) */
7
+ readonly rule: () => string;
8
+ /** Indent a line by two spaces */
9
+ readonly line: (text: string) => string;
10
+ /** Dim / secondary text */
11
+ readonly dim: (text: string) => string;
12
+ /** Inline tag badge (cyan background) */
13
+ readonly tag: (text: string) => string;
14
+ /** Green checkmark item */
15
+ readonly ok: (text: string) => string;
16
+ /** Red cross item */
17
+ readonly no: (text: string) => string;
18
+ /**
19
+ * Renders a layer import-direction row.
20
+ *
21
+ * @param from source layer name
22
+ * @param to target layer name
23
+ * @param allowed true → green arrow, false → red cross
24
+ */
25
+ readonly arrow: (from: string, to: string, allowed: boolean) => string;
26
+ };
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fmt = void 0;
7
+ /**
8
+ * Shared chalk formatting helpers used across CLI output.
9
+ *
10
+ * Keeping these in one place ensures visual consistency and
11
+ * makes it easy to restyle the entire CLI from a single file.
12
+ */
13
+ const chalk_1 = __importDefault(require("chalk"));
14
+ exports.fmt = {
15
+ /** Bold white section heading */
16
+ h1: (text) => chalk_1.default.bold.white(`\n ${text}\n`),
17
+ /** Bold cyan sub-heading */
18
+ h2: (text) => chalk_1.default.bold.cyan(`\n ${text}`),
19
+ /** Dim horizontal rule (58 chars) */
20
+ rule: () => chalk_1.default.gray(` ${'─'.repeat(58)}`),
21
+ /** Indent a line by two spaces */
22
+ line: (text) => ` ${text}`,
23
+ /** Dim / secondary text */
24
+ dim: (text) => chalk_1.default.gray(text),
25
+ /** Inline tag badge (cyan background) */
26
+ tag: (text) => chalk_1.default.bgCyan.black(` ${text} `),
27
+ /** Green checkmark item */
28
+ ok: (text) => ` ${chalk_1.default.green('✓')} ${text}`,
29
+ /** Red cross item */
30
+ no: (text) => ` ${chalk_1.default.red('✗')} ${text}`,
31
+ /**
32
+ * Renders a layer import-direction row.
33
+ *
34
+ * @param from source layer name
35
+ * @param to target layer name
36
+ * @param allowed true → green arrow, false → red cross
37
+ */
38
+ arrow: (from, to, allowed) => ` ${chalk_1.default.cyan(from.padEnd(12))} ${allowed ? chalk_1.default.green('→') : chalk_1.default.red('✗')} ${chalk_1.default.white(to)}`,
39
+ };
40
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/shared/format.ts"],"names":[],"mappings":";;;;;;AAAA;;;;;GAKG;AACH,kDAAyB;AAEZ,QAAA,GAAG,GAAG;IACjB,iCAAiC;IACjC,EAAE,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,eAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC;IAEvD,4BAA4B;IAC5B,EAAE,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IAEpD,qCAAqC;IACrC,IAAI,EAAE,GAAG,EAAE,CAAC,eAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;IAE7C,kCAAkC;IAClC,IAAI,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE;IAEnC,2BAA2B;IAC3B,GAAG,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC;IAEvC,yCAAyC;IACzC,GAAG,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,eAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC;IAEtD,2BAA2B;IAC3B,EAAE,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,eAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE;IAErD,qBAAqB;IACrB,EAAE,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,eAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE;IAEnD;;;;;;OAMG;IACH,KAAK,EAAE,CAAC,IAAY,EAAE,EAAU,EAAE,OAAgB,EAAE,EAAE,CACpD,KAAK,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,eAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,eAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,eAAK,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE;CAC9F,CAAA"}
@@ -1,4 +1,4 @@
1
- import { SliceType } from '../types/folder-tree';
1
+ import type { SliceType } from '../types/folder-tree';
2
2
  type SliceFileMap = Record<string, string>;
3
3
  /**
4
4
  * Returns a map of { relativeFilePath: fileContent } for a given slice type.
@@ -9,9 +9,10 @@ function toPascalCase(name) {
9
9
  return name.charAt(0).toUpperCase() + name.slice(1);
10
10
  }
11
11
  // ---------------------------------------------------------------------------
12
- // Individual file templates
12
+ // Shared file templates
13
13
  // ---------------------------------------------------------------------------
14
- const indexTemplate = (name) => {
14
+ /** Public barrel re-exports ui component + its props type */
15
+ const uiBarrelTemplate = (name) => {
15
16
  const pascal = toPascalCase(name);
16
17
  return [
17
18
  `export { ${pascal} } from './ui/${pascal}'`,
@@ -19,7 +20,22 @@ const indexTemplate = (name) => {
19
20
  '',
20
21
  ].join('\n');
21
22
  };
22
- const componentIndexTemplate = (name) => {
23
+ /** Public barrel for entity — re-exports model types and api */
24
+ const entityBarrelTemplate = (name) => {
25
+ const pascal = toPascalCase(name);
26
+ return [
27
+ `export type { ${pascal}State } from './model'`,
28
+ `export { fetch${pascal} } from './api'`,
29
+ '',
30
+ ].join('\n');
31
+ };
32
+ /** Public barrel for page — re-exports Page component */
33
+ const pageBarrelTemplate = (name) => {
34
+ const pascal = toPascalCase(name);
35
+ return [`export { ${pascal}Page } from './ui/${pascal}Page'`, ''].join('\n');
36
+ };
37
+ /** Public barrel for flat component */
38
+ const componentBarrelTemplate = (name) => {
23
39
  const pascal = toPascalCase(name);
24
40
  return [
25
41
  `export { ${pascal} } from './${pascal}'`,
@@ -27,6 +43,7 @@ const componentIndexTemplate = (name) => {
27
43
  '',
28
44
  ].join('\n');
29
45
  };
46
+ /** React function component */
30
47
  const reactComponentTemplate = (name) => {
31
48
  const pascal = toPascalCase(name);
32
49
  return [
@@ -44,6 +61,7 @@ const reactComponentTemplate = (name) => {
44
61
  ``,
45
62
  ].join('\n');
46
63
  };
64
+ /** State / stores / hooks */
47
65
  const modelTemplate = (name) => {
48
66
  const pascal = toPascalCase(name);
49
67
  return [
@@ -55,6 +73,7 @@ const modelTemplate = (name) => {
55
73
  ``,
56
74
  ].join('\n');
57
75
  };
76
+ /** Data fetching / mutations */
58
77
  const apiTemplate = (name) => {
59
78
  const pascal = toPascalCase(name);
60
79
  return [
@@ -76,33 +95,66 @@ const apiTemplate = (name) => {
76
95
  function getSliceFiles(sliceType, name) {
77
96
  const pascal = toPascalCase(name);
78
97
  switch (sliceType) {
98
+ /**
99
+ * feature — full vertical slice (FSD)
100
+ * Owns its own UI, business logic (model) and server communication (api).
101
+ */
79
102
  case 'feature':
80
- case 'entity':
81
103
  return {
82
- 'index.ts': indexTemplate(name),
104
+ 'index.ts': uiBarrelTemplate(name),
83
105
  [`ui/${pascal}.tsx`]: reactComponentTemplate(name),
84
106
  'model/index.ts': modelTemplate(name),
85
107
  'api/index.ts': apiTemplate(name),
86
108
  };
109
+ /**
110
+ * entity — data-layer slice (FSD)
111
+ * Represents a domain object: model + api, no UI of its own.
112
+ * UI is assembled in features/widgets that consume the entity.
113
+ */
114
+ case 'entity':
115
+ return {
116
+ 'index.ts': entityBarrelTemplate(name),
117
+ 'model/index.ts': modelTemplate(name),
118
+ 'api/index.ts': apiTemplate(name),
119
+ };
120
+ /**
121
+ * widget — composite UI block (FSD)
122
+ * Combines multiple features/entities into a self-contained UI block.
123
+ * Has UI and may have local model state, but does NOT own server calls.
124
+ */
87
125
  case 'widget':
88
126
  return {
89
- 'index.ts': indexTemplate(name),
127
+ 'index.ts': uiBarrelTemplate(name),
90
128
  [`ui/${pascal}.tsx`]: reactComponentTemplate(name),
91
129
  'model/index.ts': modelTemplate(name),
92
130
  };
131
+ /**
132
+ * page — route-level shell (FSD)
133
+ * Thin composition layer: assembles widgets/features for a route.
134
+ * No model or api — those belong to the layers below.
135
+ */
93
136
  case 'page':
94
137
  return {
95
- 'index.ts': [`export { ${pascal}Page } from './ui/${pascal}Page'`, ''].join('\n'),
138
+ 'index.ts': pageBarrelTemplate(name),
96
139
  [`ui/${pascal}Page.tsx`]: reactComponentTemplate(`${pascal}Page`),
97
140
  };
141
+ /**
142
+ * component — pure UI atom (FSD shared/ui or Modular shared/ui)
143
+ * Stateless, presentational, reusable across the whole codebase.
144
+ * Flat structure — no sub-directories.
145
+ */
98
146
  case 'component':
99
147
  return {
100
- 'index.ts': componentIndexTemplate(name),
148
+ 'index.ts': componentBarrelTemplate(name),
101
149
  [`${pascal}.tsx`]: reactComponentTemplate(name),
102
150
  };
151
+ /**
152
+ * module — full vertical slice (Modular architecture)
153
+ * Equivalent to a feature in FSD: owns UI, model and api.
154
+ */
103
155
  case 'module':
104
156
  return {
105
- 'index.ts': indexTemplate(name),
157
+ 'index.ts': uiBarrelTemplate(name),
106
158
  [`ui/${pascal}.tsx`]: reactComponentTemplate(name),
107
159
  'model/index.ts': modelTemplate(name),
108
160
  'api/index.ts': apiTemplate(name),
@@ -1 +1 @@
1
- {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/templates/files.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/templates/files.ts"],"names":[],"mappings":"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"}
@@ -10,14 +10,28 @@ export type Architecture = 'fsd' | 'modular';
10
10
  */
11
11
  export type SliceType = 'feature' | 'entity' | 'widget' | 'page' | 'component' | 'module';
12
12
  /**
13
- * Project config stored in .component-forge.json
13
+ * Project config written by `init`, read by all commands.
14
+ *
15
+ * Can live in:
16
+ * - forge.config.ts (recommended — full TypeScript + IntelliSense)
17
+ * - .component-forge.json (legacy — still supported for backwards compatibility)
18
+ *
19
+ * @example forge.config.ts
20
+ * ```ts
21
+ * import { defineConfig } from '@xanahlight/component-forge'
22
+ *
23
+ * export default defineConfig({
24
+ * architecture: 'fsd',
25
+ * srcDir: 'src',
26
+ * })
27
+ * ```
14
28
  */
15
29
  export interface ProjectConfig {
16
30
  architecture: Architecture;
17
31
  srcDir: string;
18
32
  /**
19
33
  * Optional path to a directory containing custom Handlebars (.hbs) templates.
20
- * Resolved relative to the project root (where .component-forge.json lives).
34
+ * Resolved relative to the project root.
21
35
  *
22
36
  * Directory structure must mirror the built-in layout:
23
37
  * <templatesDir>/<sliceType>/<file>.hbs
@@ -28,3 +42,18 @@ export interface ProjectConfig {
28
42
  */
29
43
  templates?: string;
30
44
  }
45
+ /**
46
+ * Type-safe config helper — provides IntelliSense and compile-time validation
47
+ * in forge.config.ts.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * import { defineConfig } from '@xanahlight/component-forge'
52
+ *
53
+ * export default defineConfig({
54
+ * architecture: 'fsd',
55
+ * srcDir: 'src',
56
+ * })
57
+ * ```
58
+ */
59
+ export declare function defineConfig(config: ProjectConfig): ProjectConfig;
@@ -1,3 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defineConfig = defineConfig;
4
+ /**
5
+ * Type-safe config helper — provides IntelliSense and compile-time validation
6
+ * in forge.config.ts.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { defineConfig } from '@xanahlight/component-forge'
11
+ *
12
+ * export default defineConfig({
13
+ * architecture: 'fsd',
14
+ * srcDir: 'src',
15
+ * })
16
+ * ```
17
+ */
18
+ function defineConfig(config) {
19
+ return config;
20
+ }
3
21
  //# sourceMappingURL=folder-tree.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"folder-tree.js","sourceRoot":"","sources":["../../src/types/folder-tree.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"folder-tree.js","sourceRoot":"","sources":["../../src/types/folder-tree.ts"],"names":[],"mappings":";;AAoEA,oCAEC;AAhBD;;;;;;;;;;;;;GAaG;AACH,SAAgB,YAAY,CAAC,MAAqB;IAChD,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -1,11 +1,24 @@
1
- import { ProjectConfig } from '../types/folder-tree';
2
- export declare const CONFIG_FILENAME = ".component-forge.json";
1
+ import type { ProjectConfig } from '../types/folder-tree';
2
+ export declare const CONFIG_FILENAMES: {
3
+ readonly ts: "forge.config.ts";
4
+ readonly js: "forge.config.js";
5
+ readonly json: ".component-forge.json";
6
+ };
3
7
  /**
4
- * Reads and returns the project config from .component-forge.json.
5
- * Exits with a user-friendly error if the file does not exist.
8
+ * Reads and returns the project config.
9
+ *
10
+ * Resolution order:
11
+ * 1. forge.config.ts
12
+ * 2. forge.config.js
13
+ * 3. .component-forge.json (legacy)
14
+ *
15
+ * Exits with a user-friendly error if no config is found.
6
16
  */
7
- export declare function loadProjectConfig(): ProjectConfig;
17
+ export declare function loadProjectConfig(projectRoot?: string): ProjectConfig;
8
18
  /**
9
- * Writes the project config to .component-forge.json.
19
+ * Writes the project config to .component-forge.json (legacy format).
20
+ * Used by the `init` command when scaffolding a new project.
21
+ *
22
+ * Note: users can migrate to forge.config.ts at any time for better DX.
10
23
  */
11
24
  export declare function writeProjectConfig(config: ProjectConfig, projectRoot: string): void;
@@ -3,31 +3,93 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.CONFIG_FILENAME = void 0;
6
+ exports.CONFIG_FILENAMES = void 0;
7
7
  exports.loadProjectConfig = loadProjectConfig;
8
8
  exports.writeProjectConfig = writeProjectConfig;
9
- const fs_extra_1 = __importDefault(require("fs-extra"));
10
9
  const node_path_1 = __importDefault(require("node:path"));
10
+ const fs_extra_1 = __importDefault(require("fs-extra"));
11
+ const jiti_1 = require("jiti");
11
12
  const logger_1 = require("./logger");
12
- exports.CONFIG_FILENAME = '.component-forge.json';
13
+ // ---------------------------------------------------------------------------
14
+ // Config file resolution order
15
+ //
16
+ // 1. forge.config.ts ← recommended (TypeScript, IntelliSense)
17
+ // 2. forge.config.js ← for projects that prefer plain JS
18
+ // 3. .component-forge.json ← legacy (backwards compat)
19
+ // ---------------------------------------------------------------------------
20
+ exports.CONFIG_FILENAMES = {
21
+ ts: 'forge.config.ts',
22
+ js: 'forge.config.js',
23
+ json: '.component-forge.json',
24
+ };
25
+ /**
26
+ * Attempts to load forge.config.ts / forge.config.js via jiti (zero-config TS runner).
27
+ * Returns the default export, or null if the file does not exist.
28
+ */
29
+ function loadTsConfig(projectRoot) {
30
+ for (const filename of [exports.CONFIG_FILENAMES.ts, exports.CONFIG_FILENAMES.js]) {
31
+ const configPath = node_path_1.default.join(projectRoot, filename);
32
+ if (!fs_extra_1.default.existsSync(configPath))
33
+ continue;
34
+ try {
35
+ // jiti executes TypeScript on-the-fly — no build step needed
36
+ const jiti = (0, jiti_1.createJiti)(__filename, { interopDefault: true });
37
+ const mod = jiti(configPath);
38
+ const config = mod.default ?? mod;
39
+ if (!config || typeof config !== 'object') {
40
+ logger_1.logger.error(`${filename} must export a default config object.`);
41
+ logger_1.logger.info(`Use defineConfig({ architecture: 'fsd', srcDir: 'src' }) as the default export.`);
42
+ process.exit(1);
43
+ }
44
+ return config;
45
+ }
46
+ catch (err) {
47
+ logger_1.logger.error(`Failed to load ${filename}: ${err.message}`);
48
+ process.exit(1);
49
+ }
50
+ }
51
+ return null;
52
+ }
13
53
  /**
14
- * Reads and returns the project config from .component-forge.json.
15
- * Exits with a user-friendly error if the file does not exist.
54
+ * Reads and returns the project config.
55
+ *
56
+ * Resolution order:
57
+ * 1. forge.config.ts
58
+ * 2. forge.config.js
59
+ * 3. .component-forge.json (legacy)
60
+ *
61
+ * Exits with a user-friendly error if no config is found.
16
62
  */
17
- function loadProjectConfig() {
18
- const configPath = node_path_1.default.join(process.cwd(), exports.CONFIG_FILENAME);
19
- if (!fs_extra_1.default.existsSync(configPath)) {
20
- logger_1.logger.error(`No ${exports.CONFIG_FILENAME} found.`);
21
- logger_1.logger.info('Run "component-forge init <architecture>" first.');
22
- process.exit(1);
63
+ function loadProjectConfig(projectRoot = process.cwd()) {
64
+ // 1 & 2 — TypeScript / JS config
65
+ const tsConfig = loadTsConfig(projectRoot);
66
+ if (tsConfig)
67
+ return tsConfig;
68
+ // 3 — Legacy JSON config
69
+ const jsonPath = node_path_1.default.join(projectRoot, exports.CONFIG_FILENAMES.json);
70
+ if (fs_extra_1.default.existsSync(jsonPath)) {
71
+ return fs_extra_1.default.readJsonSync(jsonPath);
23
72
  }
24
- return fs_extra_1.default.readJsonSync(configPath);
73
+ // Nothing found
74
+ logger_1.logger.error(`No forge.config.ts (or ${exports.CONFIG_FILENAMES.json}) found.`);
75
+ logger_1.logger.info('Run "component-forge init" to create a config, or create forge.config.ts manually:');
76
+ logger_1.logger.info('');
77
+ logger_1.logger.info(" import { defineConfig } from '@xanahlight/component-forge'");
78
+ logger_1.logger.info('');
79
+ logger_1.logger.info(" export default defineConfig({");
80
+ logger_1.logger.info(" architecture: 'fsd',");
81
+ logger_1.logger.info(" srcDir: 'src',");
82
+ logger_1.logger.info(" })");
83
+ process.exit(1);
25
84
  }
26
85
  /**
27
- * Writes the project config to .component-forge.json.
86
+ * Writes the project config to .component-forge.json (legacy format).
87
+ * Used by the `init` command when scaffolding a new project.
88
+ *
89
+ * Note: users can migrate to forge.config.ts at any time for better DX.
28
90
  */
29
91
  function writeProjectConfig(config, projectRoot) {
30
- const configPath = node_path_1.default.join(projectRoot, exports.CONFIG_FILENAME);
92
+ const configPath = node_path_1.default.join(projectRoot, exports.CONFIG_FILENAMES.json);
31
93
  fs_extra_1.default.writeJsonSync(configPath, config, { spaces: 2 });
32
94
  }
33
95
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":";;;;;;AAYA,8CAUC;AAKD,gDAGC;AA9BD,wDAAyB;AACzB,0DAA4B;AAG5B,qCAAiC;AAEpB,QAAA,eAAe,GAAG,uBAAuB,CAAA;AAEtD;;;GAGG;AACH,SAAgB,iBAAiB;IAC/B,MAAM,UAAU,GAAG,mBAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,uBAAe,CAAC,CAAA;IAE5D,IAAI,CAAC,kBAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,eAAM,CAAC,KAAK,CAAC,MAAM,uBAAe,SAAS,CAAC,CAAA;QAC5C,eAAM,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAA;QAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,OAAO,kBAAE,CAAC,YAAY,CAAC,UAAU,CAAkB,CAAA;AACrD,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,MAAqB,EAAE,WAAmB;IAC3E,MAAM,UAAU,GAAG,mBAAI,CAAC,IAAI,CAAC,WAAW,EAAE,uBAAe,CAAC,CAAA;IAC1D,kBAAE,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;AACrD,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { SliceType } from '../types/folder-tree';
1
+ import type { SliceType } from '../types/folder-tree';
2
2
  /**
3
3
  * Resolves the file map for a slice, merging custom templates over built-in defaults.
4
4
  *
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.resolveSliceFiles = resolveSliceFiles;
7
+ const node_path_1 = __importDefault(require("node:path"));
7
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
8
9
  const handlebars_1 = __importDefault(require("handlebars"));
9
- const node_path_1 = __importDefault(require("node:path"));
10
10
  const files_1 = require("../templates/files");
11
11
  /** "auth" → "Auth", "userProfile" → "UserProfile" */
12
12
  function toPascalCase(str) {