1+ import chalk from 'chalk' ;
12import { Command } from 'commander' ;
23import { execa } from 'execa' ;
34import fs from 'fs-extra' ;
@@ -8,21 +9,23 @@ import {
89 choosePackageManager ,
910 choosePreset ,
1011} from '../utils/prompts.js' ;
11- import type { InitOptions , PackageManager , Preset } from '../utils/types.js' ;
12+ import { PRESETS , type InitOptions , type PackageManager , type Preset } from '../utils/types.js' ;
1213import { resolvePm , resolvePreset } from '../utils/utils.js' ;
14+ import { ANGULAR_CLI_VERSION } from '../utils/versions.js' ;
15+ import { fileURLToPath } from 'node:url' ;
1316
1417/**
1518 * Ensures that the target directory exists and is empty.
1619 * If the directory already exists and is not empty, prompts the user to confirm whether to continue.
1720 * Returns true if the directory is ready for use, false if the user aborted.
1821 **/
19- async function ensureCleanEmptyDir ( dir : string , projectName : string ) : Promise < boolean > {
22+ async function ensureCleanEmptyDir ( dir : string ) : Promise < boolean > {
2023 if ( await fs . pathExists ( dir ) ) {
2124 const entries = await fs . readdir ( dir ) ;
2225 if ( entries . length > 0 ) {
23- const ok = await askContinueInNonEmptyDir ( projectName ) ;
26+ const ok = await askContinueInNonEmptyDir ( dir ) ;
2427 if ( ! ok ) {
25- console . log ( 'Aborted.' ) ;
28+ console . log ( '❌ ' + chalk . red ( ' Aborted.') ) ;
2629 return false ;
2730 }
2831 }
@@ -34,11 +37,11 @@ async function ensureCleanEmptyDir(dir: string, projectName: string): Promise<bo
3437/** Logs the starting info for the initialization process. */
3538function logStarting ( repoRoot : string , preset : Preset , pm : PackageManager ) : void {
3639 console . log ( '' ) ;
37- console . log ( '🚀 Starting swagstack project initialization...' ) ;
40+ console . log ( '🚀 ' + chalk . cyanBright ( ' Starting swagstack project initialization...') ) ;
3841 console . log ( '' ) ;
39- console . log ( `Creating monorepo: ${ repoRoot } ` ) ;
40- console . log ( `Preset: ${ preset } ` ) ;
41- console . log ( `Package Manager: ${ pm } ` ) ;
42+ console . log ( `Creating monorepo: ${ chalk . green ( repoRoot ) } ` ) ;
43+ console . log ( `Preset: ${ chalk . green ( preset ) } ` ) ;
44+ console . log ( `Package Manager: ${ chalk . green ( pm ) } ` ) ;
4245 console . log ( '' ) ;
4346}
4447
@@ -47,60 +50,68 @@ async function run(cmd: string, args: string[], cwd: string): Promise<void> {
4750 await execa ( cmd , args , { cwd, stdio : 'inherit' } ) ;
4851}
4952
50- async function writeRootFiles ( repoRoot : string , projectName : string , pm : PackageManager ) : Promise < void > {
51- const rootPkg = {
52- name : projectName ,
53- private : true ,
54- workspaces : [ 'apps/*' ] ,
55- scripts : {
56- 'dev:frontend' : `${ pm } --prefix apps/frontend start` ,
57- } ,
58- } ;
59- await fs . writeJson ( path . join ( repoRoot , 'package.json' ) , rootPkg , { spaces : 2 } ) ;
60-
61- if ( pm === 'pnpm' ) {
62- await fs . writeFile ( path . join ( repoRoot , 'pnpm-workspace.yaml' ) , `packages:\n - 'apps/*'\n` ) ;
63- }
64-
65- await fs . writeFile (
66- path . join ( repoRoot , 'README.md' ) ,
67- [
68- `# ${ name } ` ,
69- '' ,
70- 'Generated with [swagstack](https://github.com/inpercima/swagstack).' ,
71- '' ,
72- '## Next steps' ,
73- '' ,
74- `\`\`\`bash` ,
75- `cd ${ name } ` ,
76- `${ pm } install` ,
77- `${ pm } run dev:frontend` ,
78- `\`\`\`` ,
79- '' ,
80- ] . join ( '\n' ) ,
81- ) ;
53+ /** Writes the root-level files like package.json and README.md. */
54+ async function writeRootFiles (
55+ repoRoot : string ,
56+ projectName : string ,
57+ pm : PackageManager ,
58+ ) : Promise < void > {
59+ const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) ) ;
60+ fs . copyFile ( path . join ( __dirname , '../templates/root/.gitattributes' ) , path . join ( repoRoot , '.gitattributes' ) ) ;
61+ // const rootPkg = {
62+ // name: projectName,
63+ // private: true,
64+ // workspaces: ['apps/*'],
65+ // scripts: {
66+ // 'dev:frontend': `${pm} --prefix apps/frontend start`,
67+ // },
68+ // };
69+ // await fs.writeJson(path.join(repoRoot, 'package.json'), rootPkg, { spaces: 2 });
70+ // if (pm === 'pnpm') {
71+ // await fs.writeFile(path.join(repoRoot, 'pnpm-workspace.yaml'), `packages:\n - 'apps/*'\n`);
72+ // }
73+ // await fs.writeFile(
74+ // path.join(repoRoot, 'README.md'),
75+ // [
76+ // `# ${projectName}`,
77+ // '',
78+ // 'Generated with [swagstack](https://github.com/inpercima/swagstack).',
79+ // '',
80+ // '## Next steps',
81+ // '',
82+ // `\`\`\`bash`,
83+ // `cd ${projectName}`,
84+ // `${pm} install`,
85+ // `${pm} run dev:frontend`,
86+ // `\`\`\``,
87+ // '',
88+ // ].join('\n'),
89+ // );
8290}
8391
84- async function createAngularFrontend ( repoRoot : string , pm : PackageManager ) : Promise < void > {
85- const appsDir = path . join ( repoRoot , 'apps' ) ;
86- const frontendDir = path . join ( appsDir , 'frontend' ) ;
87- await fs . ensureDir ( appsDir ) ;
88-
92+ async function createAngularFrontendSkeleton (
93+ repoRoot : string ,
94+ projectName : string ,
95+ preset : Preset ,
96+ pm : PackageManager ,
97+ ) : Promise < void > {
98+ const isAngularOnly = preset === PRESETS . ANGULAR_ONLY ;
99+ const workingDir = isAngularOnly ? process . cwd ( ) : repoRoot ;
89100 await run (
90101 'npx' ,
91102 [
92103 '-y' ,
93- ' @angular/cli@latest' ,
104+ ` @angular/cli@${ ANGULAR_CLI_VERSION } ` ,
94105 'new' ,
95- 'frontend' ,
96- '--directory' ,
97- frontendDir ,
106+ isAngularOnly ? projectName : 'frontend' ,
107+ '--interactive=false' ,
108+ '--skip-git' ,
109+ '--style=css' ,
110+ '--routing' ,
98111 '--package-manager' ,
99112 pm ,
100- '--skip-git' ,
101- '--skip-tests' ,
102113 ] ,
103- repoRoot ,
114+ workingDir ,
104115 ) ;
105116}
106117
@@ -170,37 +181,36 @@ async function startInitialization(
170181 logStarting ( repoRoot , preset , pm ) ;
171182
172183 await writeRootFiles ( repoRoot , projectName , pm ) ;
173- await createAngularFrontend ( repoRoot , pm ) ;
184+ await createAngularFrontendSkeleton ( repoRoot , projectName , preset , pm ) ;
174185
175- if ( preset === 'preset-angular-java' ) {
186+ if ( preset === PRESETS . ANGULAR_JAVA ) {
176187 await createJavaBackendSkeleton ( repoRoot ) ;
177- } else if ( preset === 'preset-angular-php' ) {
188+ } else if ( preset === PRESETS . ANGULAR_PHP ) {
178189 await createPhpBackendSkeleton ( repoRoot ) ;
179190 }
180191
181192 console . log ( '' ) ;
182- console . log ( '✔ Done! Next steps:') ;
193+ console . log ( `✔ ${ chalk . green ( ' Done! Next steps:') } ` ) ;
183194 console . log ( '' ) ;
184- console . log ( ` cd ${ projectName } ` ) ;
185- console . log ( ` ${ pm } install` ) ;
186- console . log ( ` ${ pm } run dev:frontend` ) ;
195+ console . log ( ` cd ${ chalk . green ( projectName ) } ` ) ;
196+ console . log ( ` ${ chalk . green ( pm ) } install` ) ;
197+ console . log ( ` ${ chalk . green ( pm ) } run dev:frontend` ) ;
187198 console . log ( '' ) ;
188199}
189200
190201export function initCommand ( ) : Command {
191202 const cmd = new Command ( 'init' ) ;
192203 cmd
193204 . argument ( '[name]' , 'Project folder name (monorepo root)' )
194- . option ( '--preset <preset>' , 'preset-angular-only | preset-angular-java | preset-angular-php ' )
205+ . option ( '--preset <preset>' , 'Preset to use (e.g. preset-angular-only) ' )
195206 . option ( '--pm <pm>' , 'pnpm | npm | yarn (default: pnpm)' )
196207 . action ( async ( name : string | undefined , opts : InitOptions ) => {
197-
198208 const projectName = name ?? ( await askProjectName ( ) ) ;
199209 const preset : Preset = resolvePreset ( opts . preset ) ?? ( await choosePreset ( ) ) ;
200210 const pm : PackageManager = resolvePm ( opts . pm ) ?? ( await choosePackageManager ( ) ) ;
201211 const repoRoot = path . resolve ( process . cwd ( ) , projectName ) ;
202212
203- if ( await ensureCleanEmptyDir ( repoRoot , projectName ) ) {
213+ if ( await ensureCleanEmptyDir ( repoRoot ) ) {
204214 startInitialization ( repoRoot , projectName , preset , pm ) . catch ( ( err ) => {
205215 console . error ( 'Initialization failed:' , err ) ;
206216 process . exit ( 1 ) ;
0 commit comments