create-xeikit-app 1.1.0 → 1.2.1

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.
package/README.md CHANGED
@@ -2,19 +2,91 @@
2
2
 
3
3
  [![npm version][npm-version-src]][npm-version-href]
4
4
 
5
- ## Usage
5
+ ## 🚀 Quick Start
6
6
 
7
- You can use [these templates](https://github.com/xeikit/starter/tree/templates/templates) to create a new project by running the following command:
7
+ You can use [these templates](https://github.com/xeikit/starter-templates/tree/main/packages) to create a new project by running the following command:
8
8
 
9
9
  ```bash
10
10
  npx create-xeikit-app
11
11
  ```
12
12
 
13
- This will prompt you to select a template and then create a new project using that template.
13
+ Follow the interactive prompts to select your preferred template and get coding immediately!
14
+
15
+ ## ✨ Development
16
+
17
+ ### Release Process
18
+
19
+ This project uses an enhanced multi-stage release process with comprehensive safety checks:
20
+
21
+ #### Available Release Commands
22
+
23
+ ```bash
24
+ # Enhanced release with safety checks
25
+ pnpm release:enhanced
26
+
27
+ # Dry run (preview changes without publishing)
28
+ pnpm release:dry
29
+
30
+ # Quick release (skip confirmations)
31
+ pnpm release:quick
32
+
33
+ # Legacy release (simple one-stage process)
34
+ pnpm release
35
+ ```
36
+
37
+ #### Release Options
38
+
39
+ ```bash
40
+ # Perform a dry run
41
+ node scripts/release.mjs --dry-run
42
+
43
+ # Quick release with patch version
44
+ node scripts/release.mjs --quick patch
45
+
46
+ # Skip specific steps
47
+ node scripts/release.mjs --skip-tests --skip-lint
48
+
49
+ # Release types
50
+ node scripts/release.mjs [patch|minor|major|prerelease]
51
+ ```
52
+
53
+ #### Release Stages
54
+
55
+ 1. **Pre-release Checks**
56
+
57
+ - Git status validation
58
+ - Branch verification (main/master)
59
+ - User confirmation
60
+
61
+ 2. **Quality Assurance**
62
+
63
+ - Linting (`pnpm lint:fix`)
64
+ - Testing (`pnpm test:ci`)
65
+
66
+ 3. **Build & Release**
67
+ - Project build (`pnpm build`)
68
+ - Changelog generation (`changelogen`)
69
+ - Package publishing (`pnpm publish`)
70
+
71
+ #### Safety Features
72
+
73
+ - **Dry Run**: Preview all changes without making actual modifications
74
+ - **Git Validation**: Warns about uncommitted changes and non-main branches
75
+ - **User Confirmation**: Interactive prompts for critical steps
76
+ - **Error Handling**: Clear error messages and recovery suggestions
77
+ - **Quick Mode**: Skip confirmations for urgent releases
14
78
 
15
79
  ## 📄 License
16
80
 
17
- [MIT](./LICENSE) License © 2025–Present [XeicuLy](https://github.com/XeicuLy)
81
+ This project is licensed under the [MIT License](./LICENSE).
82
+
83
+ ## 🔗 Related
84
+
85
+ - [starter-templates](https://github.com/xeikit/starter-templates) - Starter Templates
86
+
87
+ ---
88
+
89
+ Made with ❤️ by the [xeikit](https://github.com/xeikit) team
18
90
 
19
91
  <!-- Badges -->
20
92
 
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
- "use strict";const citty=require("citty"),r=require("consola"),utils=require("consola/utils"),pathe=require("pathe"),stdEnv=require("std-env"),node_fs=require("node:fs"),tinyexec=require("tinyexec"),nypm=require("nypm"),giget=require("giget");function _interopDefaultCompat(e){return e&&typeof e=="object"&&"default"in e?e.default:e}const r__default=_interopDefaultCompat(r),name="create-xeikit-app",version="1.0.0",description="CLI tool for scaffolding projects with xeikit/starter templates.",Ok=e=>({success:!0,data:e}),Err=e=>({success:!1,error:e}),isOk=e=>e.success,createDirectoryExistsMessage=e=>{const t=pathe.relative(process.cwd(),e)||e;return`The directory ${utils.colors.cyan(t)} already exists. Please choose a different directory.`},checkDirectoryExists=e=>node_fs.existsSync(e),handleError=e=>{r__default.error(e.toString()),process.exit(1)},validateDirectoryDoesNotExist=e=>checkDirectoryExists(e)?Err(createDirectoryExistsMessage(e)):Ok(e),verifyDirectoryDoesNotExist=e=>{const t=validateDirectoryDoesNotExist(e);t.success||(r__default.error(t.error),process.exit(1))},resolvePath=(e,t)=>pathe.resolve(e,t),validateGitInitParam=e=>e===void 0?Err("Git initialization parameter is undefined"):Ok(e),promptForGitInitialization=async()=>{try{const e=await r__default.prompt("Initialize git repository?",{type:"confirm",cancel:"reject"});return Ok(e)}catch(e){return Err(e instanceof Error?e:new Error("Git initialization prompt cancelled"))}},determineGitInitialization=async e=>{const t=validateGitInitParam(e);return isOk(t)?Ok(t.data):await promptForGitInitialization()},createGitInitArgs=e=>["init",e],executeGitInit=async e=>{try{return await tinyexec.x("git",createGitInitArgs(e),{throwOnError:!0,nodeOptions:{stdio:"inherit"}}),Ok(void 0)}catch(t){return Err(t instanceof Error?t:new Error("Git initialization failed"))}},initializeGitIfRequested=async(e,t)=>{const a=await determineGitInitialization(e);if(isOk(a)||process.exit(1),!a.data)return;r__default.info(`Initializing git repository...
2
- `);const n=await executeGitInit(t);isOk(n)||r__default.warn(`Failed to initialize git repository: ${n.error.message}`)},DEFAULT_REGISTRY="https://raw.githubusercontent.com/xeikit/starter/templates/templates",DEFAULT_TEMPLATE_NAME="nuxt3",PACKAGE_MANAGERS={npm:void 0,yarn:void 0,pnpm:void 0,bun:void 0,deno:void 0},PACKAGE_MANAGER_OPTIONS=Object.keys(PACKAGE_MANAGERS),TEMPLATE_OPTIONS=[{label:"Nuxt3",value:"nuxt3"},{label:"React Router (framework)",value:"react-router"}],parsePackageManagerFromUserAgent=e=>{const[t]=e.split("/");return PACKAGE_MANAGER_OPTIONS.includes(t)?t:void 0},detectCurrentPackageManager=()=>{const e=process.env.npm_config_user_agent;return e?parsePackageManagerFromUserAgent(e):void 0},validatePackageManagerArg=e=>e?PACKAGE_MANAGER_OPTIONS.includes(e)?Ok(e):Err(`Invalid package manager: ${e}`):Err("Package manager argument is empty"),createPackageManagerSelectOptions=e=>PACKAGE_MANAGER_OPTIONS.map(t=>({label:t,value:t,hint:e===t?"current":void 0})),promptForPackageManager=async e=>{try{const t=await r__default.prompt("Which package manager would you like to use?",{type:"select",options:createPackageManagerSelectOptions(e),initial:e,cancel:"reject"});return Ok(t)}catch(t){return Err(t instanceof Error?t:new Error("Package manager selection cancelled"))}},selectPackageManager=async e=>{const t=validatePackageManagerArg(e);if(isOk(t))return t.data;const a=detectCurrentPackageManager(),n=await promptForPackageManager(a);if(isOk(n))return n.data;process.exit(1)},validateInstallationPromptResult=e=>typeof e!="boolean"?Err("Please specify whether to install dependencies."):Ok(e),promptForDependenciesInstallation=async e=>{try{const t=await r__default.prompt("Do you want to install dependencies?",{type:"confirm",initial:e,cancel:"reject"}),a=validateInstallationPromptResult(t);return isOk(a)?a:Err(new Error(a.error))}catch(t){return Err(t instanceof Error?t:new Error("Dependencies installation prompt cancelled"))}},confirmDependenciesInstallation=async e=>{const t=await promptForDependenciesInstallation(e);if(isOk(t))return t.data;const a=t.error instanceof Error?t.error.message:String(t.error);a?.includes("Please specify")&&r__default.error(a),process.exit(1)},createInstallationConfig=(e,t)=>({cwd:e,packageManager:{name:t,command:t}}),installDependenciesWithResult=async(e,t)=>{try{return await nypm.installDependencies(createInstallationConfig(e,t)),Ok(void 0)}catch(a){return Err(a instanceof Error?a:new Error("Dependencies installation failed"))}},installDependenciesIfRequested=async(e,t,a)=>{if(e===!1){r__default.info("Skipping dependency installation.");return}r__default.start("Installing dependencies...");const n=await installDependenciesWithResult(t,a);if(isOk(n)){r__default.success("Installation completed.");return}handleError(n.error)},validateTemplateArg=e=>!e||e.trim()===""?Err("Template argument is empty or undefined"):Ok(e),validateTemplatePromptResult=e=>typeof e!="string"?Err("Please specify a template name."):Ok(e||DEFAULT_TEMPLATE_NAME),promptForTemplate=async()=>{try{const e=await r__default.prompt("Choose a template",{type:"select",options:TEMPLATE_OPTIONS,cancel:"reject"}),t=validateTemplatePromptResult(e);return isOk(t)?t:Err(new Error(t.error))}catch(e){return Err(e instanceof Error?e:new Error("Template selection cancelled"))}},selectTemplate=async e=>{const t=validateTemplateArg(e);if(isOk(t))return t.data;const a=await promptForTemplate();if(isOk(a))return a.data;r__default.error(a.error.message||"Template selection cancelled"),process.exit(1)},downloadTemplateWithResult=async(e,t)=>{try{const a=await giget.downloadTemplate(e,{dir:t,registry:DEFAULT_REGISTRY});return Ok(a)}catch(a){return Err(a instanceof Error?a:new Error("Template download failed"))}},downloadTemplateAndHandleErrors=async(e,t)=>{const a=await downloadTemplateWithResult(e,t);return isOk(a)?a.data:handleError(a.error)},validateDirectoryArg=e=>!e||e.trim()===""?Err("Directory argument is empty"):Ok(e.trim()),createProjectDirectoryPromptConfig=()=>({placeholder:"./my-project",type:"text",default:"./my-project",cancel:"reject"}),promptForProjectDirectory=async()=>{try{const e=await r__default.prompt("Where would you like to create your project?",createProjectDirectoryPromptConfig());return Ok(e)}catch(e){return Err(e instanceof Error?e:new Error("Project directory prompt cancelled"))}},getProjectDirectory=async e=>{const t=validateDirectoryArg(e);if(isOk(t))return t.data;const a=await promptForProjectDirectory();if(isOk(a))return a.data;process.exit(1)},createProjectConfig=(e,t)=>({projectDir:t,templateDownloadPath:resolvePath(e,t),cwd:resolvePath(e,"")}),displayProjectCreationInfo=e=>{const t=pathe.relative(e.cwd,e.templateDownloadPath)||e.templateDownloadPath;r__default.info(`Creating a new project in ${utils.colors.cyan(t)}.`)},createFinalInstructions=(e,t,a,n)=>({successMessage:`
1
+ "use strict";const citty=require("citty"),r=require("consola"),utils=require("consola/utils"),pathe=require("pathe"),stdEnv=require("std-env"),node_fs=require("node:fs"),tinyexec=require("tinyexec"),nypm=require("nypm"),giget=require("giget");function _interopDefaultCompat(e){return e&&typeof e=="object"&&"default"in e?e.default:e}const r__default=_interopDefaultCompat(r),name="create-xeikit-app",version="1.2.0",description="CLI tool for scaffolding projects with xeikit/starter templates.",Ok=e=>({success:!0,data:e}),Err=e=>({success:!1,error:e}),isOk=e=>e.success,createDirectoryExistsMessage=e=>{const t=pathe.relative(process.cwd(),e)||e;return`The directory ${utils.colors.cyan(t)} already exists. Please choose a different directory.`},checkDirectoryExists=e=>node_fs.existsSync(e),handleError=e=>{r__default.error(e.toString()),process.exit(1)},validateDirectoryDoesNotExist=e=>checkDirectoryExists(e)?Err(createDirectoryExistsMessage(e)):Ok(e),verifyDirectoryDoesNotExist=e=>{const t=validateDirectoryDoesNotExist(e);t.success||(r__default.error(t.error),process.exit(1))},resolvePath=(e,t)=>pathe.resolve(e,t),validateGitInitParam=e=>e===void 0?Err("Git initialization parameter is undefined"):Ok(e),promptForGitInitialization=async()=>{try{const e=await r__default.prompt("Initialize git repository?",{type:"confirm",cancel:"reject"});return Ok(e)}catch(e){return Err(e instanceof Error?e:new Error("Git initialization prompt cancelled"))}},determineGitInitialization=async e=>{const t=validateGitInitParam(e);return isOk(t)?Ok(t.data):await promptForGitInitialization()},createGitInitArgs=e=>["init",e],executeGitInit=async e=>{try{return await tinyexec.x("git",createGitInitArgs(e),{throwOnError:!0,nodeOptions:{stdio:"inherit"}}),Ok(void 0)}catch(t){return Err(t instanceof Error?t:new Error("Git initialization failed"))}},initializeGitIfRequested=async(e,t)=>{const a=await determineGitInitialization(e);if(isOk(a)||process.exit(1),!a.data)return;r__default.info(`Initializing git repository...
2
+ `);const n=await executeGitInit(t);isOk(n)||r__default.warn(`Failed to initialize git repository: ${n.error.message}`)},DEFAULT_REGISTRY="https://raw.githubusercontent.com/xeikit/starter-templates/main/templates",DEFAULT_TEMPLATE_NAME="nuxt3",PACKAGE_MANAGERS={npm:void 0,yarn:void 0,pnpm:void 0,bun:void 0,deno:void 0},PACKAGE_MANAGER_OPTIONS=Object.keys(PACKAGE_MANAGERS),TEMPLATE_OPTIONS=[{label:"Nuxt3",value:"nuxt3"},{label:"React Router (framework)",value:"react-router"},{label:"TanStack Start (Beta)",value:"tanstack-start"}],parsePackageManagerFromUserAgent=e=>{const[t]=e.split("/");return PACKAGE_MANAGER_OPTIONS.includes(t)?t:void 0},detectCurrentPackageManager=()=>{const e=process.env.npm_config_user_agent;return e?parsePackageManagerFromUserAgent(e):void 0},validatePackageManagerArg=e=>e?PACKAGE_MANAGER_OPTIONS.includes(e)?Ok(e):Err(`Invalid package manager: ${e}`):Err("Package manager argument is empty"),createPackageManagerSelectOptions=e=>PACKAGE_MANAGER_OPTIONS.map(t=>({label:t,value:t,hint:e===t?"current":void 0})),promptForPackageManager=async e=>{try{const t=await r__default.prompt("Which package manager would you like to use?",{type:"select",options:createPackageManagerSelectOptions(e),initial:e,cancel:"reject"});return Ok(t)}catch(t){return Err(t instanceof Error?t:new Error("Package manager selection cancelled"))}},selectPackageManager=async e=>{const t=validatePackageManagerArg(e);if(isOk(t))return t.data;const a=detectCurrentPackageManager(),n=await promptForPackageManager(a);if(isOk(n))return n.data;process.exit(1)},validateInstallationPromptResult=e=>typeof e!="boolean"?Err("Please specify whether to install dependencies."):Ok(e),promptForDependenciesInstallation=async e=>{try{const t=await r__default.prompt("Do you want to install dependencies?",{type:"confirm",initial:e,cancel:"reject"}),a=validateInstallationPromptResult(t);return isOk(a)?a:Err(new Error(a.error))}catch(t){return Err(t instanceof Error?t:new Error("Dependencies installation prompt cancelled"))}},confirmDependenciesInstallation=async e=>{const t=await promptForDependenciesInstallation(e);if(isOk(t))return t.data;const a=t.error instanceof Error?t.error.message:String(t.error);a?.includes("Please specify")&&r__default.error(a),process.exit(1)},createInstallationConfig=(e,t)=>({cwd:e,packageManager:{name:t,command:t}}),installDependenciesWithResult=async(e,t)=>{try{return await nypm.installDependencies(createInstallationConfig(e,t)),Ok(void 0)}catch(a){return Err(a instanceof Error?a:new Error("Dependencies installation failed"))}},installDependenciesIfRequested=async(e,t,a)=>{if(e===!1){r__default.info("Skipping dependency installation.");return}r__default.start("Installing dependencies...");const n=await installDependenciesWithResult(t,a);if(isOk(n)){r__default.success("Installation completed.");return}handleError(n.error)},validateTemplateArg=e=>!e||e.trim()===""?Err("Template argument is empty or undefined"):Ok(e),validateTemplatePromptResult=e=>typeof e!="string"?Err("Please specify a template name."):Ok(e||DEFAULT_TEMPLATE_NAME),promptForTemplate=async()=>{try{const e=await r__default.prompt("Choose a template",{type:"select",options:TEMPLATE_OPTIONS,cancel:"reject"}),t=validateTemplatePromptResult(e);return isOk(t)?t:Err(new Error(t.error))}catch(e){return Err(e instanceof Error?e:new Error("Template selection cancelled"))}},selectTemplate=async e=>{const t=validateTemplateArg(e);if(isOk(t))return t.data;const a=await promptForTemplate();if(isOk(a))return a.data;r__default.error(a.error.message||"Template selection cancelled"),process.exit(1)},downloadTemplateWithResult=async(e,t)=>{try{const a=await giget.downloadTemplate(e,{dir:t,registry:DEFAULT_REGISTRY});return Ok(a)}catch(a){return Err(a instanceof Error?a:new Error("Template download failed"))}},downloadTemplateAndHandleErrors=async(e,t)=>{const a=await downloadTemplateWithResult(e,t);return isOk(a)?a.data:handleError(a.error)},validateDirectoryArg=e=>!e||e.trim()===""?Err("Directory argument is empty"):Ok(e.trim()),createProjectDirectoryPromptConfig=()=>({placeholder:"./my-project",type:"text",default:"./my-project",cancel:"reject"}),promptForProjectDirectory=async()=>{try{const e=await r__default.prompt("Where would you like to create your project?",createProjectDirectoryPromptConfig());return Ok(e)}catch(e){return Err(e instanceof Error?e:new Error("Project directory prompt cancelled"))}},getProjectDirectory=async e=>{const t=validateDirectoryArg(e);if(isOk(t))return t.data;const a=await promptForProjectDirectory();if(isOk(a))return a.data;process.exit(1)},createProjectConfig=(e,t)=>({projectDir:t,templateDownloadPath:resolvePath(e,t),cwd:resolvePath(e,"")}),displayProjectCreationInfo=e=>{const t=pathe.relative(e.cwd,e.templateDownloadPath)||e.templateDownloadPath;r__default.info(`Creating a new project in ${utils.colors.cyan(t)}.`)},createFinalInstructions=(e,t,a,n)=>({successMessage:`
3
3
  \u{1F389} Starter project has been created with the \`${n}\` template.`,nextStepsTitle:`
4
4
  \u{1F680} Next steps:
5
5
  `,changeDirectory:`cd ${utils.colors.cyan(e)}`,installCommand:t?null:`${utils.colors.cyan(a)} install`,devCommand:`${utils.colors.cyan(a)} run dev`,happyCoding:`
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import{defineCommand as f,runMain as w}from"citty";import a from"consola";import{colors as l}from"consola/utils";import{resolve as h,relative as u}from"pathe";import{hasTTY as E}from"std-env";import{existsSync as P}from"node:fs";import{x as v}from"tinyexec";import{installDependencies as k}from"nypm";import{downloadTemplate as D}from"giget";const x="create-xeikit-app",I="1.0.0",T="CLI tool for scaffolding projects with xeikit/starter templates.",o=e=>({success:!0,data:e}),n=e=>({success:!1,error:e}),c=e=>e.success,j=e=>{const t=u(process.cwd(),e)||e;return`The directory ${l.cyan(t)} already exists. Please choose a different directory.`},C=e=>P(e),y=e=>{a.error(e.toString()),process.exit(1)},A=e=>C(e)?n(j(e)):o(e),M=e=>{const t=A(e);t.success||(a.error(t.error),process.exit(1))},g=(e,t)=>h(e,t),F=e=>e===void 0?n("Git initialization parameter is undefined"):o(e),G=async()=>{try{const e=await a.prompt("Initialize git repository?",{type:"confirm",cancel:"reject"});return o(e)}catch(e){return n(e instanceof Error?e:new Error("Git initialization prompt cancelled"))}},S=async e=>{const t=F(e);return c(t)?o(t.data):await G()},b=e=>["init",e],R=async e=>{try{return await v("git",b(e),{throwOnError:!0,nodeOptions:{stdio:"inherit"}}),o(void 0)}catch(t){return n(t instanceof Error?t:new Error("Git initialization failed"))}},$=async(e,t)=>{const r=await S(e);if(c(r)||process.exit(1),!r.data)return;a.info(`Initializing git repository...
2
- `);const i=await R(t);c(i)||a.warn(`Failed to initialize git repository: ${i.error.message}`)},z="https://raw.githubusercontent.com/xeikit/starter/templates/templates",O="nuxt3",_={npm:void 0,yarn:void 0,pnpm:void 0,bun:void 0,deno:void 0},p=Object.keys(_),N=[{label:"Nuxt3",value:"nuxt3"},{label:"React Router (framework)",value:"react-router"}],L=e=>{const[t]=e.split("/");return p.includes(t)?t:void 0},W=()=>{const e=process.env.npm_config_user_agent;return e?L(e):void 0},H=e=>e?p.includes(e)?o(e):n(`Invalid package manager: ${e}`):n("Package manager argument is empty"),U=e=>p.map(t=>({label:t,value:t,hint:e===t?"current":void 0})),q=async e=>{try{const t=await a.prompt("Which package manager would you like to use?",{type:"select",options:U(e),initial:e,cancel:"reject"});return o(t)}catch(t){return n(t instanceof Error?t:new Error("Package manager selection cancelled"))}},K=async e=>{const t=H(e);if(c(t))return t.data;const r=W(),i=await q(r);if(c(i))return i.data;process.exit(1)},Y=e=>typeof e!="boolean"?n("Please specify whether to install dependencies."):o(e),B=async e=>{try{const t=await a.prompt("Do you want to install dependencies?",{type:"confirm",initial:e,cancel:"reject"}),r=Y(t);return c(r)?r:n(new Error(r.error))}catch(t){return n(t instanceof Error?t:new Error("Dependencies installation prompt cancelled"))}},J=async e=>{const t=await B(e);if(c(t))return t.data;const r=t.error instanceof Error?t.error.message:String(t.error);r?.includes("Please specify")&&a.error(r),process.exit(1)},Q=(e,t)=>({cwd:e,packageManager:{name:t,command:t}}),V=async(e,t)=>{try{return await k(Q(e,t)),o(void 0)}catch(r){return n(r instanceof Error?r:new Error("Dependencies installation failed"))}},X=async(e,t,r)=>{if(e===!1){a.info("Skipping dependency installation.");return}a.start("Installing dependencies...");const i=await V(t,r);if(c(i)){a.success("Installation completed.");return}y(i.error)},Z=e=>!e||e.trim()===""?n("Template argument is empty or undefined"):o(e),ee=e=>typeof e!="string"?n("Please specify a template name."):o(e||O),te=async()=>{try{const e=await a.prompt("Choose a template",{type:"select",options:N,cancel:"reject"}),t=ee(e);return c(t)?t:n(new Error(t.error))}catch(e){return n(e instanceof Error?e:new Error("Template selection cancelled"))}},re=async e=>{const t=Z(e);if(c(t))return t.data;const r=await te();if(c(r))return r.data;a.error(r.error.message||"Template selection cancelled"),process.exit(1)},ae=async(e,t)=>{try{const r=await D(e,{dir:t,registry:z});return o(r)}catch(r){return n(r instanceof Error?r:new Error("Template download failed"))}},ne=async(e,t)=>{const r=await ae(e,t);return c(r)?r.data:y(r.error)},oe=e=>!e||e.trim()===""?n("Directory argument is empty"):o(e.trim()),ie=()=>({placeholder:"./my-project",type:"text",default:"./my-project",cancel:"reject"}),ce=async()=>{try{const e=await a.prompt("Where would you like to create your project?",ie());return o(e)}catch(e){return n(e instanceof Error?e:new Error("Project directory prompt cancelled"))}},se=async e=>{const t=oe(e);if(c(t))return t.data;const r=await ce();if(c(r))return r.data;process.exit(1)},le=(e,t)=>({projectDir:t,templateDownloadPath:g(e,t),cwd:g(e,"")}),pe=e=>{const t=u(e.cwd,e.templateDownloadPath)||e.templateDownloadPath;a.info(`Creating a new project in ${l.cyan(t)}.`)},de=(e,t,r,i)=>({successMessage:`
1
+ import{defineCommand as f,runMain as w}from"citty";import a from"consola";import{colors as l}from"consola/utils";import{resolve as h,relative as u}from"pathe";import{hasTTY as E}from"std-env";import{existsSync as P}from"node:fs";import{x as v}from"tinyexec";import{installDependencies as k}from"nypm";import{downloadTemplate as D}from"giget";const x="create-xeikit-app",I="1.2.0",T="CLI tool for scaffolding projects with xeikit/starter templates.",o=e=>({success:!0,data:e}),n=e=>({success:!1,error:e}),c=e=>e.success,j=e=>{const t=u(process.cwd(),e)||e;return`The directory ${l.cyan(t)} already exists. Please choose a different directory.`},C=e=>P(e),y=e=>{a.error(e.toString()),process.exit(1)},A=e=>C(e)?n(j(e)):o(e),M=e=>{const t=A(e);t.success||(a.error(t.error),process.exit(1))},g=(e,t)=>h(e,t),F=e=>e===void 0?n("Git initialization parameter is undefined"):o(e),S=async()=>{try{const e=await a.prompt("Initialize git repository?",{type:"confirm",cancel:"reject"});return o(e)}catch(e){return n(e instanceof Error?e:new Error("Git initialization prompt cancelled"))}},G=async e=>{const t=F(e);return c(t)?o(t.data):await S()},b=e=>["init",e],R=async e=>{try{return await v("git",b(e),{throwOnError:!0,nodeOptions:{stdio:"inherit"}}),o(void 0)}catch(t){return n(t instanceof Error?t:new Error("Git initialization failed"))}},$=async(e,t)=>{const r=await G(e);if(c(r)||process.exit(1),!r.data)return;a.info(`Initializing git repository...
2
+ `);const i=await R(t);c(i)||a.warn(`Failed to initialize git repository: ${i.error.message}`)},z="https://raw.githubusercontent.com/xeikit/starter-templates/main/templates",O="nuxt3",_={npm:void 0,yarn:void 0,pnpm:void 0,bun:void 0,deno:void 0},p=Object.keys(_),N=[{label:"Nuxt3",value:"nuxt3"},{label:"React Router (framework)",value:"react-router"},{label:"TanStack Start (Beta)",value:"tanstack-start"}],L=e=>{const[t]=e.split("/");return p.includes(t)?t:void 0},W=()=>{const e=process.env.npm_config_user_agent;return e?L(e):void 0},H=e=>e?p.includes(e)?o(e):n(`Invalid package manager: ${e}`):n("Package manager argument is empty"),U=e=>p.map(t=>({label:t,value:t,hint:e===t?"current":void 0})),q=async e=>{try{const t=await a.prompt("Which package manager would you like to use?",{type:"select",options:U(e),initial:e,cancel:"reject"});return o(t)}catch(t){return n(t instanceof Error?t:new Error("Package manager selection cancelled"))}},K=async e=>{const t=H(e);if(c(t))return t.data;const r=W(),i=await q(r);if(c(i))return i.data;process.exit(1)},Y=e=>typeof e!="boolean"?n("Please specify whether to install dependencies."):o(e),B=async e=>{try{const t=await a.prompt("Do you want to install dependencies?",{type:"confirm",initial:e,cancel:"reject"}),r=Y(t);return c(r)?r:n(new Error(r.error))}catch(t){return n(t instanceof Error?t:new Error("Dependencies installation prompt cancelled"))}},J=async e=>{const t=await B(e);if(c(t))return t.data;const r=t.error instanceof Error?t.error.message:String(t.error);r?.includes("Please specify")&&a.error(r),process.exit(1)},Q=(e,t)=>({cwd:e,packageManager:{name:t,command:t}}),V=async(e,t)=>{try{return await k(Q(e,t)),o(void 0)}catch(r){return n(r instanceof Error?r:new Error("Dependencies installation failed"))}},X=async(e,t,r)=>{if(e===!1){a.info("Skipping dependency installation.");return}a.start("Installing dependencies...");const i=await V(t,r);if(c(i)){a.success("Installation completed.");return}y(i.error)},Z=e=>!e||e.trim()===""?n("Template argument is empty or undefined"):o(e),ee=e=>typeof e!="string"?n("Please specify a template name."):o(e||O),te=async()=>{try{const e=await a.prompt("Choose a template",{type:"select",options:N,cancel:"reject"}),t=ee(e);return c(t)?t:n(new Error(t.error))}catch(e){return n(e instanceof Error?e:new Error("Template selection cancelled"))}},re=async e=>{const t=Z(e);if(c(t))return t.data;const r=await te();if(c(r))return r.data;a.error(r.error.message||"Template selection cancelled"),process.exit(1)},ae=async(e,t)=>{try{const r=await D(e,{dir:t,registry:z});return o(r)}catch(r){return n(r instanceof Error?r:new Error("Template download failed"))}},ne=async(e,t)=>{const r=await ae(e,t);return c(r)?r.data:y(r.error)},oe=e=>!e||e.trim()===""?n("Directory argument is empty"):o(e.trim()),ie=()=>({placeholder:"./my-project",type:"text",default:"./my-project",cancel:"reject"}),ce=async()=>{try{const e=await a.prompt("Where would you like to create your project?",ie());return o(e)}catch(e){return n(e instanceof Error?e:new Error("Project directory prompt cancelled"))}},se=async e=>{const t=oe(e);if(c(t))return t.data;const r=await ce();if(c(r))return r.data;process.exit(1)},le=(e,t)=>({projectDir:t,templateDownloadPath:g(e,t),cwd:g(e,"")}),pe=e=>{const t=u(e.cwd,e.templateDownloadPath)||e.templateDownloadPath;a.info(`Creating a new project in ${l.cyan(t)}.`)},de=(e,t,r,i)=>({successMessage:`
3
3
  \u{1F389} Starter project has been created with the \`${i}\` template.`,nextStepsTitle:`
4
4
  \u{1F680} Next steps:
5
5
  `,changeDirectory:`cd ${l.cyan(e)}`,installCommand:t?null:`${l.cyan(r)} install`,devCommand:`${l.cyan(r)} run dev`,happyCoding:`
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-xeikit-app",
3
3
  "type": "module",
4
- "version": "1.1.0",
4
+ "version": "1.2.1",
5
5
  "author": "XeicuLy",
6
6
  "description": "CLI tool for scaffolding projects with xeikit/starter templates.",
7
7
  "keywords": [
@@ -79,7 +79,11 @@
79
79
  "build": "unbuild",
80
80
  "dev": "unbuild --stub",
81
81
  "command": "jiti bin/cli.mjs",
82
- "release": "pnpm lint:fix && pnpm build && changelogen --release --push",
82
+ "release": "pnpm lint:fix && pnpm test:ci && pnpm build && changelogen --release --push && pnpm publish",
83
+ "release:enhanced": "node scripts/release.mjs",
84
+ "release:dry": "node scripts/release.mjs --dry-run",
85
+ "release:quick": "node scripts/release.mjs --quick",
86
+ "release:safe": "node scripts/release.mjs --skip-validation",
83
87
  "biome": "biome check .",
84
88
  "biome:fix": "biome check --write .",
85
89
  "biome:ci": "biome ci .",