@@ -15,9 +15,73 @@ import {
1515} from "./utils.js" ;
1616
1717// Parse command line arguments
18- const argv = minimist ( process . argv . slice ( 2 ) ) ;
18+ const argv = minimist ( process . argv . slice ( 2 ) , {
19+ string : [ 'name' , 'domain' , 'author' , 'uiTool' ] ,
20+ boolean : [ 'help' , 'version' ] ,
21+ alias : {
22+ h : 'help' ,
23+ v : 'version' ,
24+ n : 'name' ,
25+ d : 'domain' ,
26+ a : 'author' ,
27+ u : 'uiTool'
28+ }
29+ } ) ;
30+
1931const targetDir = argv . _ [ 0 ] ;
2032
33+ /**
34+ * Show help information
35+ */
36+ function showHelp ( ) {
37+ console . log ( `
38+ 🚀 Halo Plugin Creator
39+
40+ Usage:
41+ pnpm create halo-plugin [directory] [options]
42+
43+ Options:
44+ -n, --name <name> Plugin name (e.g., my-awesome-plugin)
45+ -d, --domain <domain> Domain for group and package name (e.g., com.example)
46+ -a, --author <author> Author name
47+ -u, --uiTool <tool> UI build tool (rsbuild or vite)
48+ -h, --help Show this help message
49+ -v, --version Show version number
50+
51+ Examples:
52+ pnpm create halo-plugin demo --name=demo --domain=com.example --author=ryanwang --uiTool=rsbuild
53+ pnpm create halo-plugin --name my-plugin --domain com.example --author "John Doe" --uiTool vite
54+ pnpm create halo-plugin
55+ ` ) ;
56+ }
57+
58+ /**
59+ * Show version information
60+ */
61+ function showVersion ( ) {
62+ // Read version from package.json
63+ const packagePath = path . join ( path . dirname ( new URL ( import . meta. url ) . pathname ) , '..' , 'package.json' ) ;
64+ try {
65+ const packageJson = JSON . parse ( fs . readFileSync ( packagePath , 'utf8' ) ) ;
66+ console . log ( packageJson . version || '1.0.0' ) ;
67+ } catch {
68+ console . log ( '1.0.0' ) ;
69+ }
70+ }
71+
72+ /**
73+ * Validate UI tool parameter
74+ * @param {string } uiTool - UI tool name
75+ * @returns {boolean|string } True if valid, error message if invalid
76+ */
77+ function validateUITool ( uiTool ) {
78+ const validTools = [ 'rsbuild' , 'vite' ] ;
79+ if ( ! validTools . includes ( uiTool ) ) {
80+ return `UI tool must be one of: ${ validTools . join ( ', ' ) } ` ;
81+ }
82+ return true ;
83+ }
84+
2185/**
2286 * Check if directory is empty
2387 * @param {string } dir - Directory path
@@ -78,62 +142,127 @@ function getProjectPath(targetDir, projectName) {
78142}
79143
80144async function main ( ) {
145+ // Handle help and version flags
146+ if ( argv . help ) {
147+ showHelp ( ) ;
148+ process . exit ( 0 ) ;
149+ }
150+
151+ if ( argv . version ) {
152+ showVersion ( ) ;
153+ process . exit ( 0 ) ;
154+ }
155+
81156 console . log ( "🚀 Welcome to Halo Plugin Creator!\n" ) ;
82157
83158 try {
84159 // Validate target directory early (if user specified one)
85160 validateTargetDir ( targetDir ) ;
86161
87- // Get user input
88- const answers = await prompts ( [
89- {
90- type : "text" ,
91- name : "name" ,
92- message : "Plugin name:" ,
93- hint : "e.g., my-awesome-plugin" ,
94- validate : validateProjectName ,
95- } ,
96- {
97- type : "text" ,
98- name : "domain" ,
99- message : "Domain (for group and package name):" ,
100- hint : "e.g., com.example" ,
101- validate : validateDomain ,
102- } ,
103- {
104- type : "text" ,
105- name : "author" ,
106- message : "Author name:" ,
107- initial : getCurrentUser ( ) ,
108- } ,
109- {
110- type : "select" ,
111- name : "uiTool" ,
112- message : "Choose UI build tool:" ,
113- choices : [
114- {
115- title : "Rsbuild" ,
116- value : "rsbuild" ,
117- description : "The Rspack Powered Build Tool(Recommended)" ,
118- } ,
119- {
120- title : "Vite" ,
121- value : "vite" ,
122- description : "The Build Tool for the Web" ,
123- } ,
124- ] ,
125- } ,
126- ] ) ;
127-
128- // If user cancelled input
129- if (
130- ! answers . name ||
131- ! answers . domain ||
132- ! answers . author ||
133- ! answers . uiTool
134- ) {
135- console . log ( "❌ Operation cancelled" ) ;
136- process . exit ( 0 ) ;
162+ // Check if all required parameters are provided via command line
163+ const hasAllParams = argv . name && argv . domain && argv . author && argv . uiTool ;
164+
165+ let answers = { } ;
166+
167+ if ( hasAllParams ) {
168+ // Validate command line arguments
169+ const nameValidation = validateProjectName ( argv . name ) ;
170+ if ( nameValidation !== true ) {
171+ throw new Error ( `Invalid plugin name: ${ nameValidation } ` ) ;
172+ }
173+
174+ const domainValidation = validateDomain ( argv . domain ) ;
175+ if ( domainValidation !== true ) {
176+ throw new Error ( `Invalid domain: ${ domainValidation } ` ) ;
177+ }
178+
179+ const uiToolValidation = validateUITool ( argv . uiTool ) ;
180+ if ( uiToolValidation !== true ) {
181+ throw new Error ( `Invalid UI tool: ${ uiToolValidation } ` ) ;
182+ }
183+
184+ // Use command line arguments
185+ answers = {
186+ name : argv . name ,
187+ domain : argv . domain ,
188+ author : argv . author ,
189+ uiTool : argv . uiTool
190+ } ;
191+
192+ console . log ( "📋 Using command line arguments:" ) ;
193+ console . log ( ` Name: ${ answers . name } ` ) ;
194+ console . log ( ` Domain: ${ answers . domain } ` ) ;
195+ console . log ( ` Author: ${ answers . author } ` ) ;
196+ console . log ( ` UI Tool: ${ answers . uiTool } ` ) ;
197+ } else {
198+ // Interactive mode - prompt for missing parameters
199+ const promptQuestions = [ ] ;
200+
201+ if ( ! argv . name ) {
202+ promptQuestions . push ( {
203+ type : "text" ,
204+ name : "name" ,
205+ message : "Plugin name:" ,
206+ hint : "e.g., my-awesome-plugin" ,
207+ validate : validateProjectName ,
208+ } ) ;
209+ }
210+
211+ if ( ! argv . domain ) {
212+ promptQuestions . push ( {
213+ type : "text" ,
214+ name : "domain" ,
215+ message : "Domain (for group and package name):" ,
216+ hint : "e.g., com.example" ,
217+ validate : validateDomain ,
218+ } ) ;
219+ }
220+
221+ if ( ! argv . author ) {
222+ promptQuestions . push ( {
223+ type : "text" ,
224+ name : "author" ,
225+ message : "Author name:" ,
226+ initial : getCurrentUser ( ) ,
227+ } ) ;
228+ }
229+
230+ if ( ! argv . uiTool ) {
231+ promptQuestions . push ( {
232+ type : "select" ,
233+ name : "uiTool" ,
234+ message : "Choose UI build tool:" ,
235+ choices : [
236+ {
237+ title : "Rsbuild" ,
238+ value : "rsbuild" ,
239+ description : "The Rspack Powered Build Tool(Recommended)" ,
240+ } ,
241+ {
242+ title : "Vite" ,
243+ value : "vite" ,
244+ description : "The Build Tool for the Web" ,
245+ } ,
246+ ] ,
247+ } ) ;
248+ }
249+
250+ // Get missing parameters through prompts
251+ const promptAnswers = await prompts ( promptQuestions ) ;
252+
253+ // If user cancelled input
254+ if ( promptQuestions . some ( q => promptAnswers [ q . name ] === undefined ) ) {
255+ console . log ( "❌ Operation cancelled" ) ;
256+ process . exit ( 0 ) ;
257+ }
258+
259+ // Merge command line args with prompt answers
260+ answers = {
261+ name : argv . name || promptAnswers . name ,
262+ domain : argv . domain || promptAnswers . domain ,
263+ author : argv . author || promptAnswers . author ,
264+ uiTool : argv . uiTool || promptAnswers . uiTool ,
265+ } ;
137266 }
138267
139268 // Process and format input
@@ -144,7 +273,7 @@ async function main() {
144273
145274 // Get project path (will check auto-generated directory if needed)
146275 const projectPath = getProjectPath ( targetDir , projectName ) ;
147- const projectDirName = path . basename ( projectPath ) ;
276+ const projectDirName = path . relative ( process . cwd ( ) , projectPath ) ;
148277
149278 // Generate project configuration
150279 const variables = {
@@ -156,25 +285,30 @@ async function main() {
156285 uiTool : answers . uiTool ,
157286 } ;
158287
159- console . log ( "\n📋 Project Configuration:" ) ;
160- console . log ( ` Name: ${ projectName } ` ) ;
161- console . log ( ` Domain: ${ group } ` ) ;
162- console . log ( ` Package: ${ packageName } ` ) ;
163- console . log ( ` Author: ${ answers . author } ` ) ;
164- console . log ( ` UI Tool: ${ answers . uiTool } ` ) ;
165- console . log ( ` Output Directory: ${ projectPath } ` ) ;
166-
167- // Confirm creation
168- const { confirm } = await prompts ( {
169- type : "confirm" ,
170- name : "confirm" ,
171- message : "Create project?" ,
172- initial : true ,
173- } ) ;
174-
175- if ( ! confirm ) {
176- console . log ( "❌ Operation cancelled" ) ;
177- process . exit ( 0 ) ;
288+ if ( ! hasAllParams ) {
289+ console . log ( "\n📋 Project Configuration:" ) ;
290+ console . log ( ` Name: ${ projectName } ` ) ;
291+ console . log ( ` Domain: ${ group } ` ) ;
292+ console . log ( ` Package: ${ packageName } ` ) ;
293+ console . log ( ` Author: ${ answers . author } ` ) ;
294+ console . log ( ` UI Tool: ${ answers . uiTool } ` ) ;
295+ console . log ( ` Output Directory: ${ projectPath } ` ) ;
296+
297+ // Confirm creation (only in interactive mode)
298+ const { confirm } = await prompts ( {
299+ type : "confirm" ,
300+ name : "confirm" ,
301+ message : "Create project?" ,
302+ initial : true ,
303+ } ) ;
304+
305+ if ( ! confirm ) {
306+ console . log ( "❌ Operation cancelled" ) ;
307+ process . exit ( 0 ) ;
308+ }
309+ } else {
310+ console . log ( ` Output Directory: ${ projectPath } \n` ) ;
311+ console . log ( "🔨 Creating project..." ) ;
178312 }
179313
180314 // Generate project
0 commit comments