@huberyyang/create-todo-vue 1.6.1 → 1.7.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.
- package/README.md +11 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/template-lit/README.md +1 -0
- package/template-lit-ts/README.md +1 -0
- package/template-vanilla/README.md +1 -0
- package/template-vanilla-ts/README.md +1 -0
- package/template-vue/README.md +1 -5
- package/template-vue-ts/README.md +1 -5
package/README.md
CHANGED
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
|
|
12
12
|
使用自定义模板快速创建最新的vue项目
|
|
13
13
|
|
|
14
|
+
内置模板生成完成后会自动执行一次 `git init`,直接就是一个干净的 git 工作区(不暂存、不提交,
|
|
15
|
+
第一个 commit 长什么样由你决定)。如果目标位置已经在某个 git 仓库里,则**跳过**这一步并给出提示——
|
|
16
|
+
在已有仓库里再建一个嵌套仓库几乎从来不是想要的结果。git 不可用或初始化失败时只会警告,
|
|
17
|
+
不影响项目本身的创建,退出码仍是 0。
|
|
18
|
+
|
|
14
19
|
### 📦 快速开始 (Usage)
|
|
15
20
|
|
|
16
21
|
#### ⏳ 交互式创建
|
|
@@ -74,6 +79,7 @@ npm create @huberyyang/todo-vue .foo --overwrite -t vue-ts --no-immediate --pack
|
|
|
74
79
|
- **拼错的参数会被指出来。**(`v1.2.0` 起)以前拼错的 flag 会被静默忽略,而且它还会把紧跟其后的目录名当成自己的值吃掉——`--overwirte my-app` 连项目名都会丢,CLI 转而追问项目名称,用户看不出哪里写错了。
|
|
75
80
|
- **非交互环境下会说清楚卡在哪。** 在 CI、脚本或 `< /dev/null` 之类拿不到输入的环境里走到提示时,会打印当前卡在哪一步、以及该改用哪个参数,然后返回 `1`。此前这里只会留下一个画到一半的选择器,没有任何解释。
|
|
76
81
|
- **依赖装不上时,项目仍然是好的。** 用 `-i` 而依赖安装失败时,**已经生成的项目不会被回滚**——会告诉你项目在哪、以及手动补装的命令,并把包管理器的退出码原样带出来(所以这时退出码不一定是 `1`)。
|
|
82
|
+
- **`git init` 失败不影响退出码。** 机器上没有 git、或初始化失败时只会警告一句,项目本身照常创建,退出码仍是 `0`——它是附加动作,不该把一次成功的创建判成失败。
|
|
77
83
|
|
|
78
84
|
#### 🟢 当前可用模板
|
|
79
85
|
|
|
@@ -92,7 +98,11 @@ npm create @huberyyang/todo-vue .foo --overwrite -t vue-ts --no-immediate --pack
|
|
|
92
98
|
- `custom-vitesse-lite` → `degit antfu-collective/vitesse-lite`(Vitesse Lite)
|
|
93
99
|
|
|
94
100
|
> 转交上游的模板由对方的脚手架直接生成,因此**不会**像内置模板那样把 `package.json` 的 `name`
|
|
95
|
-
> 和 `index.html` 的 `<title>`
|
|
101
|
+
> 和 `index.html` 的 `<title>` 改写成包名,**也不会自动 `git init`**——需要的话生成后自己改一下。
|
|
102
|
+
> 这几个还需要联网。
|
|
103
|
+
|
|
104
|
+
> 内置模板都带一份只写着模板名的占位 `README.md`(如 `# vue-ts`),它**不会**被改写成项目名,
|
|
105
|
+
> 就是留给你自己写的一张白纸。
|
|
96
106
|
|
|
97
107
|
### 📜 许可证 (License)
|
|
98
108
|
|
package/dist/index.js
CHANGED
|
@@ -68,4 +68,4 @@ ${t?s(`cyan`,H):``}
|
|
|
68
68
|
--package-name 指定 package.json 的 name
|
|
69
69
|
|
|
70
70
|
可用模板:
|
|
71
|
-
${ft(X)}`,yt=X.flatMap(e=>e.variants?.length?e.variants.map(e=>e.name):e.name),bt={_gitignore:`.gitignore`},xt=Symbol(`stdin-eof`);var St=class extends Error{step;hint;constructor(e,t){super(`需要交互才能继续:${e}`),this.step=e,this.hint=t,this.name=`NonInteractiveError`}};async function Z(e,t,n,i=r.stdin){let a=()=>{},o=new Promise(e=>{if(a=()=>e(xt),i.readableEnded){e(xt);return}i.once(`end`,a),i.once(`close`,a)});try{let r=await Promise.race([e,o]);if(r===xt)throw new St(t,n);return r}finally{i.off(`end`,a),i.off(`close`,a)}}function Ct(e){let r=n.resolve(e);for(;;){let e=n.join(r,`package.json`);if(t.existsSync(e))return e;let i=n.dirname(r);if(i===r)return;r=i}}function wt(e){let n=Ct(e);if(!n)return`unknown`;try{return JSON.parse(t.readFileSync(n,`utf-8`)).version??`unknown`}catch{return`unknown`}}function Tt(e){return e.trim().replace(/\/+$/g,``)}function Et(e){if(!e)return;let t=e.split(` `)[0].split(`/`);return{name:t[0],version:t[1]}}function Dt(){return Ve(`操作已取消`)}function Ot(e){return t.existsSync(e)?t.statSync(e).isDirectory()?`dir`:`file`:`missing`}function kt(e){let n=t.readdirSync(e);return n.length===0||n.length===1&&n[0]===`.git`}function At(e){if(!t.existsSync(e))return!1;for(let r of t.readdirSync(e))r!==`.git`&&t.rmSync(n.resolve(e,r),{recursive:!0,force:!0})}function jt(e){return/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(e)}function Mt(e){return e.trim().toLowerCase().replace(/\s+/g,`-`).replace(/^[._]/,``).replace(/[^a-z\d\-~]+/g,`-`)}function Nt(e,t){let n=t?.name||`npm`,r=n===`yarn`&&t?.version?.startsWith(`1.`);return e.replace(/^npm create (?:-- )?/,()=>n===`bun`?`bun x create-`:n===`deno`?`deno run -A npm:create-`:n===`pnpm`?`pnpm create `:e.startsWith(`npm create -- `)?`${n} create -- `:`${n} create `).replace(`@latest`,r?``:`@latest`).replace(/^npm exec /,()=>n===`pnpm`?`pnpm dlx `:n===`yarn`&&!r?`yarn dlx `:n===`bun`?`bun x `:n===`deno`?`deno run -A npm:`:`npm exec `)}function Pt(e){let{display:t,name:n,color:r,link:i}=e,a=r(t||n);return i&&(a+=` ${(0,dt.underline)(i)}`),a}function Ft(e,r){t.mkdirSync(r,{recursive:!0});for(let i of t.readdirSync(e))It(n.resolve(e,i),n.resolve(r,i))}function It(e,n){t.statSync(e).isDirectory()?Ft(e,n):t.copyFileSync(e,n)}function Lt(e){return e===`yarn`?[e]:[e,`install`]}function Rt(e,t){return e===`yarn`?[e,t]:[e,`run`,t]}function zt([e,...t],n){let{status:r,error:i}=lt.default.sync(e,t,n);return i?(console.error(`\n${e} ${t.join(` `)} 跑不起来:${i.message}`),1):r??1}function Bt(e,t){return G.step(`使用 ${t} 安装依赖...`),zt(Lt(t),{stdio:`inherit`,cwd:e})}function Vt(e,t){return e&&!t.includes(e)?{template:void 0,invalid:!0}:{template:e,invalid:!1}}function
|
|
71
|
+
${ft(X)}`,yt=X.flatMap(e=>e.variants?.length?e.variants.map(e=>e.name):e.name),bt={_gitignore:`.gitignore`},xt=Symbol(`stdin-eof`);var St=class extends Error{step;hint;constructor(e,t){super(`需要交互才能继续:${e}`),this.step=e,this.hint=t,this.name=`NonInteractiveError`}};async function Z(e,t,n,i=r.stdin){let a=()=>{},o=new Promise(e=>{if(a=()=>e(xt),i.readableEnded){e(xt);return}i.once(`end`,a),i.once(`close`,a)});try{let r=await Promise.race([e,o]);if(r===xt)throw new St(t,n);return r}finally{i.off(`end`,a),i.off(`close`,a)}}function Ct(e){let r=n.resolve(e);for(;;){let e=n.join(r,`package.json`);if(t.existsSync(e))return e;let i=n.dirname(r);if(i===r)return;r=i}}function wt(e){let n=Ct(e);if(!n)return`unknown`;try{return JSON.parse(t.readFileSync(n,`utf-8`)).version??`unknown`}catch{return`unknown`}}function Tt(e){return e.trim().replace(/\/+$/g,``)}function Et(e){if(!e)return;let t=e.split(` `)[0].split(`/`);return{name:t[0],version:t[1]}}function Dt(){return Ve(`操作已取消`)}function Ot(e){return t.existsSync(e)?t.statSync(e).isDirectory()?`dir`:`file`:`missing`}function kt(e){let n=t.readdirSync(e);return n.length===0||n.length===1&&n[0]===`.git`}function At(e){if(!t.existsSync(e))return!1;for(let r of t.readdirSync(e))r!==`.git`&&t.rmSync(n.resolve(e,r),{recursive:!0,force:!0})}function jt(e){return/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(e)}function Mt(e){return e.trim().toLowerCase().replace(/\s+/g,`-`).replace(/^[._]/,``).replace(/[^a-z\d\-~]+/g,`-`)}function Nt(e,t){let n=t?.name||`npm`,r=n===`yarn`&&t?.version?.startsWith(`1.`);return e.replace(/^npm create (?:-- )?/,()=>n===`bun`?`bun x create-`:n===`deno`?`deno run -A npm:create-`:n===`pnpm`?`pnpm create `:e.startsWith(`npm create -- `)?`${n} create -- `:`${n} create `).replace(`@latest`,r?``:`@latest`).replace(/^npm exec /,()=>n===`pnpm`?`pnpm dlx `:n===`yarn`&&!r?`yarn dlx `:n===`bun`?`bun x `:n===`deno`?`deno run -A npm:`:`npm exec `)}function Pt(e){let{display:t,name:n,color:r,link:i}=e,a=r(t||n);return i&&(a+=` ${(0,dt.underline)(i)}`),a}function Ft(e,r){t.mkdirSync(r,{recursive:!0});for(let i of t.readdirSync(e))It(n.resolve(e,i),n.resolve(r,i))}function It(e,n){t.statSync(e).isDirectory()?Ft(e,n):t.copyFileSync(e,n)}function Lt(e){return e===`yarn`?[e]:[e,`install`]}function Rt(e,t){return e===`yarn`?[e,t]:[e,`run`,t]}function zt([e,...t],n){let{status:r,error:i}=lt.default.sync(e,t,n);return i?(console.error(`\n${e} ${t.join(` `)} 跑不起来:${i.message}`),1):r??1}function Bt(e,t){return G.step(`使用 ${t} 安装依赖...`),zt(Lt(t),{stdio:`inherit`,cwd:e})}function Vt(e){let r=n.resolve(e);for(;;){let e=n.join(r,`.git`);if(t.existsSync(e))return e;let i=n.dirname(r);if(i===r)return;r=i}}function Ht(e){return zt([`git`,`init`],{stdio:`ignore`,cwd:e})}function Ut(e,t){return e&&!t.includes(e)?{template:void 0,invalid:!0}:{template:e,invalid:!1}}function Wt(e,t){let r=n.basename(n.resolve(t,e));return{name:r,needsPrompt:!jt(r)}}function Gt(e){return e===void 0||jt(e)}function Kt(e,t,n){return e===void 0?Wt(t,n):{name:e,needsPrompt:!1}}function qt(e,t){let{customCommand:n}=e.flatMap(e=>e.variants?.length?e.variants:e).find(e=>e.name===t)??{};return n}function Jt(e,t){let[n,...r]=e.split(` `);return{command:n,args:r.map(e=>e.replace(`TARGET_DIR`,t))}}function Yt(e,t){let n=e=>t[e]??e,r=e.filter(e=>e!==`package.json`).map(e=>({kind:e===`index.html`?`index-html`:`copy`,from:e,to:n(e)}));return r.push({kind:`package-json`,from:`package.json`,to:n(`package.json`)}),r}function Xt(e,t){return e.replace(/<title>.*?<\/title>/,`<title>${t}</title>`)}function Zt(e,t){let n=JSON.parse(e);return n.name=t,`${JSON.stringify(n,null,2)}\n`}function Qt(e,t,r,i=!1){let a=n.relative(e,t),o=i?`依赖安装完成,请执行:`:`创建完成,请执行:`;e!==t&&(o+=`\n cd ${a.includes(` `)?`"${a}"`:a}`);let s=i?Rt(r,`dev`):Lt(r);return o+=`\n ${s.join(` `)}`,o}function $t(e){let t=e.alias??{};return[...new Set([...e.boolean??[],...e.string??[],...Object.values(t),...Object.keys(t)])]}function en(e,t){let n=new Set(t);return Object.keys(e).filter(e=>e!==`_`&&!n.has(e))}function tn({templateDir:e,root:r,packageName:i,renameFiles:a}){t.mkdirSync(r,{recursive:!0});let o=Yt(t.readdirSync(e),a);for(let a of o){let o=n.join(e,a.from),s=n.join(r,a.to);switch(a.kind){case`index-html`:t.writeFileSync(s,Xt(t.readFileSync(o,`utf-8`),i));break;case`package-json`:t.writeFileSync(s,Zt(t.readFileSync(o,`utf-8`),i));break;case`copy`:It(o,s)}}}const nn={intro:e=>He(e),outro:e=>Ue(e),write:e=>void r.stdout.write(e)};function rn(e=nn){let t=!1,n=!1;return{open(r){e.intro(r),t=!0,n=!0},close(n=``){t&&(t=!1,e.outro(n))},markClosed(){t=!1},isOpen(){return t},restoreCursor(){n&&e.write(`\x1B[?25h`)}}}const an=o(import.meta.url),on=n.dirname(an),sn=n.resolve(an,`../..`),cn=Ge(),Q=rn();function $(){return Dt(),Q.markClosed(),1}async function ln(e=r.argv.slice(2)){let i=r.cwd(),a=(0,ut.default)(e,structuredClone(_t)),o=a._[0]?Tt(String(a._[0])):void 0,s=a.overwrite,c=a.template,l=a.immediate,u=a[`package-name`];if(a.help)return console.log(vt),0;if(a.version)return console.log(wt(on)),0;let d=en(a,$t(_t));if(d.length)return console.error(`未知参数:${d.map(e=>`--${e}`).join(`, `)}`),console.error(`运行 create-todo-vue --help 查看可用参数`),1;if(!Gt(u))return console.error(`无效的 package.json name:${u}`),console.error(`包名规则见 https://docs.npmjs.com/cli/configuring-npm/package-json#name`),1;Q.open(`create-todo-vue`);let f=Et(r.env.npm_config_user_agent),p=o;if(!p){let e=await Z(qe({message:`项目名称:`,defaultValue:gt,placeholder:gt,validate(e){return!e||Tt(e).length>0?void 0:`项目名称无效`}}),`项目名称`,`把项目名作为位置参数传入,如 create-todo-vue my-app`);if(P(e))return $();p=Tt(e)}let m=Kt(u,p,i),h=n.resolve(i,p),g=Ot(h);if(g===`file`){let e=!!s;if(!e){let t=await Z(q({message:`${p} 已存在且是一个文件,请选择如何继续`,options:[{label:`取消操作`,value:`no`},{label:`删除该文件并继续`,value:`yes`}]}),`${p} 已存在且是一个文件`,`--overwrite(会删除该文件)`);if(P(t))return $();e=t===`yes`}if(!e)return $();t.rmSync(h,{force:!0})}else if(g===`dir`&&!kt(h)){let e=s?`yes`:void 0;if(!e){let t=await Z(q({message:`${p===`.`?`当前目录`:`目标目录${p}`} 不为空,请选择如何继续`,options:[{label:`取消操作`,value:`no`},{label:`删除现有文件并继续`,value:`yes`},{label:`忽略文件并继续`,value:`ignore`}]}),`${p===`.`?`当前目录`:`目标目录${p}`} 不为空`,`--overwrite(会清空该目录,.git 保留)`);if(P(t))return $();e=t}switch(e){case`yes`:At(h);break;case`no`:return $()}}let _=m.name;if(m.needsPrompt){let e=await Z(qe({message:`请输入package.json name`,defaultValue:Mt(_),placeholder:Mt(_),validate(e){if(e&&!jt(e))return`无效的package.json name`}}),`package.json name`,`--package-name <name>`);if(P(e))return $();_=e}let{template:v,invalid:y}=Ut(c,yt),b=v;if(!b){let e=await Z(q({message:y?`${c}不是有效的模板名,请从以下选取:`:`选择模板`,options:X.map(e=>{let{color:t,name:n,display:r}=e;return{label:t(r||n),value:e}})}),`选择模板`,`-t <模板名>,可用模板见 --help`);if(P(e))return $();if(b=e.name,e.variants?.length){let t=await Z(q({message:`选择预设`,options:e.variants.map(e=>{let{name:t,customCommand:n}=e,r=n?Nt(n,f).replace(/ TARGET_DIR$/,``):void 0;return{label:Pt(e),value:t,hint:r}})}),`选择预设`,`-t <模板名>,可用模板见 --help`);if(P(t))return $();b=t}}let x=f?.name||`npm`,S=qt(X,b);if(S){let{command:e,args:t}=Jt(Nt(S,f),p);Q.close(`转交给 ${e}`);let{status:n}=lt.default.sync(e,t,{stdio:`inherit`});return n??0}if(cn.start(`正在${h}中创建模板`),tn({templateDir:n.resolve(sn,`template-${b}`),root:h,packageName:_,renameFiles:bt}),cn.stop(`模板创建成功`),Vt(h))G.info(`目标目录已在 git 仓库中,跳过 git init`);else{let e=Ht(h);e!==0&&G.warn(`git 仓库初始化失败(git 退出码 ${e}),项目已创建`)}let C=l;if(C===void 0){let e=await Z(Be({message:`是否立即使用${x}安装依赖?`}),`是否立即安装依赖`,`-i(装)或 --no-immediate(不装)`);if(P(e))return $();C=e}if(C){let e=Bt(h,x);if(e!==0)return G.warn(`项目已创建,但依赖没装上。${x} 退出码 ${e}`),G.info(Qt(i,h,x)),Q.close(`依赖安装失败`),e}return G.info(Qt(i,h,x,C)),Q.close(`程序结束`),0}async function un(){r.exitCode=1;try{r.exitCode=await ln()}catch(e){if(e instanceof St){G.error(`需要交互才能继续,但输入已结束(非 TTY,或输入已读完)\n这一步在问:${e.step}\n非交互环境请改用:${e.hint}`),Dt(),Q.markClosed();return}cn.error(`创建失败`),G.error(e instanceof Error?e.message:String(e)),Q.close(`已中止`),e instanceof Error&&e.stack&&console.error(e.stack),r.exitCode=1}finally{Q.close(),Q.restoreCursor()}}export{ln as main,un as runCli};
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# lit
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# lit-ts
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# vanilla
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# vanilla-ts
|
package/template-vue/README.md
CHANGED
|
@@ -1,5 +1 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
|
4
|
-
|
|
5
|
-
Learn more about IDE Support for Vue in the [Vue Docs Scaling up Guide](https://vuejs.org/guide/scaling-up/tooling.html#ide-support).
|
|
1
|
+
# vue
|
|
@@ -1,5 +1 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
|
4
|
-
|
|
5
|
-
Learn more about the recommended Project Setup and IDE Support in the [Vue Docs TypeScript Guide](https://vuejs.org/guide/typescript/overview.html#project-setup).
|
|
1
|
+
# vue-ts
|