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 +76 -4
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -2,19 +2,91 @@
|
|
|
2
2
|
|
|
3
3
|
[![npm version][npm-version-src]][npm-version-href]
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 🚀 Quick Start
|
|
6
6
|
|
|
7
|
-
You can use [these templates](https://github.com/xeikit/starter/tree/
|
|
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
|
-
|
|
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)
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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 .",
|