zerostarter 0.1.37 → 0.1.38-canary.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/dist/bin/index.mjs +21 -21
- package/package.json +1 -1
package/dist/bin/index.mjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{A as e,C as t,D as n,E as r,F as i,I as a,M as o,N as s,O as c,P as l,S as u,T as d,_ as f,a as p,b as m,c as ee,d as h,f as g,g as _,h as v,i as y,j as b,k as x,l as S,m as C,n as te,o as ne,p as w,r as re,s as ie,t as
|
|
3
|
-
`),i=
|
|
4
|
-
`),c=n?
|
|
5
|
-
`?l():t===`y`||t===`Y`?(i=!0,l()):t===`n`||t===`N`?(i=!1,l()):(t===`\x1B[C`||t===`\x1B[D`||t===`\x1B[A`||t===`\x1B[B`||t===`h`||t===`l`)&&(i=!i,n.write(`\r\x1b[K${
|
|
6
|
-
`)d(),n.write(`\x1b[${t.length+1}A\r\x1b[0J ${
|
|
7
|
-
`).find(e=>e.startsWith(n));return r?r.slice(n.length).trim():``},
|
|
2
|
+
import{A as e,C as t,D as n,E as r,F as i,I as a,M as o,N as s,O as c,P as l,S as u,T as d,_ as f,a as p,b as m,c as ee,d as h,f as g,g as _,h as v,i as y,j as b,k as x,l as S,m as C,n as te,o as ne,p as w,r as re,s as ie,t as ae,u as T,v as E,w as oe,x as D,y as O}from"../convert-DjNN2nhd.mjs";import{basename as se,delimiter as ce,dirname as le,join as k,parse as ue,resolve as A}from"node:path";import{existsSync as j,readFileSync as de,readdirSync as fe}from"node:fs";import{randomBytes as pe}from"node:crypto";import{createInterface as me}from"node:readline/promises";import{parseArgs as he}from"node:util";import{homedir as ge}from"node:os";var _e={name:`zerostarter`,version:`0.1.38-canary.1`,description:`Go from zero to a production-ready SaaS, rebranded and ready to ship.`,keywords:[`cli`,`saas`,`scaffold`,`starter`,`template`,`zerostarter`],homepage:`https://github.com/nrjdalal/zerostarter#readme`,bugs:`https://github.com/nrjdalal/zerostarter/issues`,license:`MIT`,author:{name:`Neeraj Dalal`,email:`admin@nrjdalal.com`,url:`https://nrjdalal.com`},repository:`nrjdalal/zerostarter`,funding:`https://github.com/sponsors/nrjdalal`,bin:{zerostarter:`dist/bin/index.mjs`},files:[`dist`],type:`module`,types:`./dist/index.d.mts`,exports:`./dist/index.mjs`,scripts:{build:`tsdown`,"check-types":`tsc --noEmit`,dev:`tsdown --watch`},devDependencies:{"@packages/config":`workspace:*`,"@types/bun":`catalog:`,"@types/node":`catalog:`,tsdown:`catalog:`,typescript:`catalog:`}};const M=()=>!!(process.stdin.isTTY&&process.stdout.isTTY),ve=(e,t=e)=>process.stdout.isTTY?`\x1b]8;;${e}\x07${t}\x1b]8;;\x07`:e,N=e=>ve(e,O(e)),P=e=>{process.stdout.write(`\n ${D(E.barStart)} ${e}\n ${D(E.bar)}\n`)},F=e=>{process.stdout.write(` ${D(E.bar)}\n ${D(E.barEnd)} ${e}\n`)},I=(e=`Cancelled`)=>{process.stdout.write(` ${D(E.barEnd)} ${d(e)}\n`)},L=e=>e.replace(/* @__PURE__ */ RegExp(`\x1B\\[[0-9;?]*[a-zA-Z]`,`g`),``).replace(/* @__PURE__ */ RegExp(`\x1B\\]8;;.*?\\x07`,`g`),``).length,R=(e,t=``,n=!1)=>{let r=`\n${e}\n`.split(`
|
|
3
|
+
`),i=L(t),a=r.reduce((e,t)=>Math.max(e,L(t)),i),o=Math.max(a,54)+2,s=r.map(e=>` ${D(E.bar)} ${e}${` `.repeat(o-L(e))}${D(E.bar)}`).join(`
|
|
4
|
+
`),c=n?E.cornerBL:E.connectL;process.stdout.write(` ${O(E.active)} ${t} ${D(E.barH.repeat(Math.max(o-i-1,1))+E.cornerTR)}\n${s}\n ${D(c+E.barH.repeat(o+2)+E.cornerBR)}\n`)},z=(e,t=[])=>{process.stdout.write(` ${O(E.active)} ${e}\n`);for(let e of t)process.stdout.write(` ${D(E.bar)} ${e}\n`)},ye=e=>{process.stdout.write(` ${u(E.active)} ${u(e)}\n`)},B=(e,t=[])=>{process.stdout.write(` ${r(E.warn)} ${r(e)}\n`);for(let e of t)process.stdout.write(` ${D(E.bar)} ${r(e)}\n`)},be=async(e,t,n)=>{let r=process.stdout,i=null;if(r.isTTY){let t=0;r.write(` ${oe(0,e)}`),i=setInterval(()=>{t+=1,r.write(`\r\x1b[K ${oe(t,e)}`)},400)}try{let e=await n();return i&&clearInterval(i),r.write(r.isTTY?`\r\x1b[K ${O(E.active)} ${t}\n`:` ${O(E.active)} ${t}\n`),e}catch(e){throw i&&clearInterval(i),r.isTTY&&r.write(`\r\x1B[K`),e}},xe=e=>{let t=e?`${u(E.radioOn)} Yes`:m(`${E.radioOff} Yes`),n=e?m(`${E.radioOff} No`):`${u(E.radioOn)} No`;return` ${D(E.bar)} ${t} ${m(`/`)} ${n}`},V=async(e,t=!0)=>{let n=process.stdout;return M()?new Promise(r=>{let i=t,a=process.stdin,o=Math.max(1,Math.ceil((5+L(e))/(n.columns||80)));n.write(` ${O(E.submit)} ${e}\n`),n.write(xe(i)),a.setRawMode(!0),a.resume(),a.setEncoding(`utf8`);let s=()=>{a.setRawMode(!1),a.pause(),a.removeListener(`data`,u)},c=()=>{n.write(`\r\x1b[K\x1b[${o}A\r\x1b[0J`)},l=()=>{s(),c(),r(i)};function u(t){t===``?(s(),c(),n.write(` ${O(E.submit)} ${m(e)}\n`),I(),process.exit(130)):t===`\r`||t===`
|
|
5
|
+
`?l():t===`y`||t===`Y`?(i=!0,l()):t===`n`||t===`N`?(i=!1,l()):(t===`\x1B[C`||t===`\x1B[D`||t===`\x1B[A`||t===`\x1B[B`||t===`h`||t===`l`)&&(i=!i,n.write(`\r\x1b[K${xe(i)}`))}a.on(`data`,u)}):(n.write(` ${O(E.active)} ${e} ${m(t?`Yes`:`No`)}\n`),t)},Se=async(e,t)=>{if(t.length===0)return[];let n=process.stdout,r=new Set(t.filter(e=>e.checked).map(e=>e.value)),i=()=>t.filter(e=>r.has(e.value)).map(e=>e.label).join(`, `)||`none`;return M()?new Promise(a=>{let o=process.stdin,s=0,c=e=>{let n=t[e],i=r.has(n.value)?u(E.checkboxOn):m(E.checkboxOff),a=e===s?n.label:m(n.label);return` ${D(E.bar)} ${i} ${a}`},l=e=>{e||n.write(`\x1b[${t.length}A`);for(let e=0;e<t.length;e++)n.write(`\r\x1b[K${c(e)}\n`)};n.write(` ${O(E.submit)} ${e}\n`),l(!0),o.setRawMode(!0),o.resume(),o.setEncoding(`utf8`);let d=()=>{o.setRawMode(!1),o.pause(),o.removeListener(`data`,f)};function f(o){if(o===``)d(),n.write(`\x1b[${t.length+1}A\r\x1b[0J ${O(E.submit)} ${m(e)}\n`),I(),process.exit(130);else if(o===`\r`||o===`
|
|
6
|
+
`)d(),n.write(`\x1b[${t.length+1}A\r\x1b[0J ${O(E.submit)} ${e} ${m(i())}\n`),a([...r]);else if(o===`\x1B[A`||o===`k`)s=(s-1+t.length)%t.length,l(!1);else if(o===`\x1B[B`||o===`j`)s=(s+1)%t.length,l(!1);else if(o===` `){let e=t[s].value;r.has(e)?r.delete(e):r.add(e),l(!1)}}o.on(`data`,f)}):(n.write(` ${O(E.submit)} ${e} ${m(i())}\n`),[...r])},Ce=async(e,t=``)=>{process.stdout.write(` ${O(E.submit)} ${e}${t?` ${m(`(${t})`)}`:``}\n`);let n=me({input:process.stdin,output:process.stdout});try{return(await n.question(` ${D(E.bar)} `)).trim()||t}finally{n.close()}},we=`pglaunch@5.5.7`,Te=async()=>w(`docker`,[`info`]),Ee=e=>{let t=k(e,`.env`);if(!x(t)){let n=k(e,`.env.example`);l(t,x(n)?b(n):``)}return t},H=(e,t)=>{let n=`${t}=`,r=b(e).split(`
|
|
7
|
+
`).find(e=>e.startsWith(n));return r?r.slice(n.length).trim():``},U=(e,t,n)=>{let r=`${t}=`,i=b(e).split(`
|
|
8
8
|
`),a=i.findIndex(e=>e.startsWith(r));if(a>=0)i[a]=`${r}${n}`;else{for(;i.length&&i[i.length-1]===``;)i.pop();i.push(`${r}${n}`,``)}l(e,i.join(`
|
|
9
|
-
`))},
|
|
10
|
-
`)}return{launch:
|
|
9
|
+
`))},De=e=>{let t=Ee(e);H(t,`BETTER_AUTH_SECRET`)||U(t,`BETTER_AUTH_SECRET`,pe(32).toString(`base64`)),H(t,`AGENT_SIGNIN_ENABLED`)||U(t,`AGENT_SIGNIN_ENABLED`,`true`)},W=e=>{let t=k(e,`.env`);return x(t)&&H(t,`POSTGRES_URL`)!==``},Oe=e=>{let t=e.match(/postgres(?:ql)?:\/\/[\w.:@\-/%?=&]+/);if(!t)return null;let n=e.match(/name "([^" ]+) :\d+" started/),r=e.match(/similar name "([^"]+)"/);return{url:t[0],container:n?n[1]:r?r[1]:``}},ke=async(e,t)=>{let n=t?[`--bun`,we,`-k`,`-c`]:[`--bun`,we,`-k`],r;try{r=await v(`bunx`,n,e)}catch(e){let t=e;r=[t.stdout,t.stderr].filter(Boolean).join(`
|
|
10
|
+
`)}return{launch:Oe(r),out:r}},Ae=e=>new Promise(t=>setTimeout(t,e)),je=async e=>{if(e)for(let t=0;t<30;t++){if(await w(`docker`,[`exec`,e,`pg_isready`,`-U`,`postgres`]))return;await Ae(1e3)}},Me=async e=>{let t=Ee(e),n=await ke(e,!1),r=n.launch?n:await ke(e,!0);if(!r.launch)throw Error(r.out.trim()||`pglaunch did not print a connection URL`);U(t,`POSTGRES_URL`,r.launch.url),await je(r.launch.container),await f(`bun`,[`run`,`db:migrate`],{cwd:e,label:`Provisioning a local Postgres database`,done:`Provisioned a local Postgres database`})},G=`gitpick@6.0.0`,K=async e=>{await f(`bun`,[`install`],{cwd:e,label:`Installing dependencies`,done:`Installed dependencies`})},Ne=async()=>{if(!await w(`bun`,[`--version`]))throw Error(`bun is not on PATH`)},Pe=async(e=Ne,t=!!process.versions.bun,n=process.env.npm_config_user_agent||``)=>{if(t||n.startsWith(`bun/`))return!0;try{return await e(),!0}catch{return!1}},Fe=async(e,t=`main`)=>{await v(`bunx`,[`--bun`,G,`https://github.com/nrjdalal/zerostarter/tree/${t}`,e])},Ie=async(e,t=`main`)=>{await v(`bunx`,[`--bun`,G,`https://github.com/nrjdalal/zerostarter/tree/${t}`,e,`-o`])},Le=async(e=`main`)=>{let t=`https://raw.githubusercontent.com/nrjdalal/zerostarter/${e}/.gitpickignore`,n=await fetch(t);if(!n.ok)throw Error(`Could not fetch .gitpickignore from ${e} (HTTP ${n.status}).`);return n.text()},Re=async e=>(await v(`git`,[`status`,`--porcelain`],e)).trim()===``,ze=async(e,t)=>{for(let n of t)try{await v(`git`,[`checkout`,`--`,n],e),await v(`git`,[`clean`,`-fd`,`--`,n],e)}catch{}},Be=async e=>{await v(`git`,[`reset`,`--hard`,`HEAD`],e),await v(`git`,[`clean`,`-fd`],e)},Ve=async(e,t,n)=>{if(!x(k(e,`.git`)))throw Error(t);if(!await Re(e))throw Error(n)},He=async(e,t,n)=>{try{await n()}catch(n){throw await Be(e),console.log(t),n}},Ue=async e=>{await v(`git`,[`init`,`-q`,`-b`,`canary`],e)},We=async(e,t)=>{await v(`git`,[`branch`,t],e)},q=async(e,t)=>{await v(`git`,[`add`,`-A`],e);try{await v(`git`,[`commit`,`--no-verify`,`-q`,`-m`,t],e)}catch{}},J=(e,t)=>{try{return he(t)}catch(t){process.stderr.write(`${d(t instanceof Error?t.message:String(t))}\n\n`),process.stdout.write(`${e}\n`),process.exit(1)}},Ge=(e=process.env.npm_config_user_agent||``)=>e.startsWith(`bun/`)?`bunx`:e.startsWith(`pnpm/`)?`pnpm dlx`:e.startsWith(`yarn/`)?`yarn dlx`:e.startsWith(`npm/`)?`npx`:`unknown`,Ke=(e=process.platform)=>e===`win32`?{cmd:`powershell`,args:[`-Command`,`irm bun.sh/install.ps1 | iex`]}:{cmd:`bash`,args:[`-c`,`curl -fsSL https://bun.sh/install | bash`]},qe=(e=process.argv.slice(2))=>[`zerostarter`,...e].join(` `),Je=()=>k(process.env.BUN_INSTALL||k(ge(),`.bun`),`bin`),Y=async(e=!1)=>{if(await Pe())return;let n=Ge(),r=`bunx --bun ${qe()}`;if(console.error(d(`Seems like you are using ${n===`unknown`?`npx/pnpx`:n} or Windows, try using:`)),console.error(t(` ${r}`)),console.error(``),e||M()&&await V(`Or install bun now and continue?`,!0)){let{cmd:e,args:n}=Ke();console.error(`Installing bun from https://bun.sh/install ...`);try{if(await _(e,n),process.env.PATH=`${Je()}${ce}${process.env.PATH||``}`,await Pe())return;console.error(d(`
|
|
11
11
|
bun is installed but isn't on this shell's PATH yet. Open a new terminal and re-run:`)),console.error(t(` ${r}`))}catch{console.error(d(`
|
|
12
|
-
Could not install bun. Install it from https://bun.sh, then re-run:`)),console.error(t(` ${r}`))}}process.exit(1)},X=[{value:`allowlist`,flag:`allowlist`,help:`Console access by email domain or address`,label:`Allowlist (grant console access by domain)`},{value:`apiDocs`,flag:`api-docs`,help:`The /api/docs API reference`,label:`API docs`},{value:`blog`,flag:`blog`,help:`The /blog`,label:`Blog`},{value:`docs`,flag:`docs`,help:`The /docs`,label:`Docs`},{value:`internalDocs`,flag:`internal-docs`,help:`The /console/docs internal docs`,label:`Internal (console) docs`},{value:`waitlist`,flag:`waitlist`,help:`The /waitlist (off leaves a plain landing home)`,label:`Waitlist (else a plain landing home)`}],
|
|
13
|
-
`),
|
|
12
|
+
Could not install bun. Install it from https://bun.sh, then re-run:`)),console.error(t(` ${r}`))}}process.exit(1)},X=[{value:`allowlist`,flag:`allowlist`,help:`Console access by email domain or address`,label:`Allowlist (grant console access by domain)`},{value:`apiDocs`,flag:`api-docs`,help:`The /api/docs API reference`,label:`API docs`},{value:`blog`,flag:`blog`,help:`The /blog`,label:`Blog`},{value:`docs`,flag:`docs`,help:`The /docs`,label:`Docs`},{value:`internalDocs`,flag:`internal-docs`,help:`The /console/docs internal docs`,label:`Internal (console) docs`},{value:`waitlist`,flag:`waitlist`,help:`The /waitlist (off leaves a plain landing home)`,label:`Waitlist (else a plain landing home)`}],Ye=X.filter(e=>!g[e.value]).map(e=>e.flag),Xe=X.map(e=>` ${`--${e.flag},`.padEnd(18)}${`--no-${e.flag}`.padEnd(21)}${e.help}`).join(`
|
|
13
|
+
`),Ze=Object.fromEntries(X.flatMap(e=>[[e.flag,{type:`boolean`}],[`no-${e.flag}`,{type:`boolean`}]])),Qe=`Usage:
|
|
14
14
|
$ bunx zerostarter init [dir] [options]
|
|
15
15
|
|
|
16
16
|
Scaffold ZeroStarter into dir (default .) as a fresh product. The author's
|
|
@@ -26,11 +26,11 @@ Options:
|
|
|
26
26
|
--dry-run Print the plan without writing anything
|
|
27
27
|
-h, --help Display help
|
|
28
28
|
|
|
29
|
-
Features (on by default, except ${
|
|
30
|
-
${
|
|
31
|
-
`).filter(e=>e.trim()).slice(-5):[])}}else S&&
|
|
32
|
-
`),`Edit and make it yours`),
|
|
33
|
-
`),`Next steps`),
|
|
29
|
+
Features (on by default, except ${Ye.join(` and `)}; pass any flag to skip the interactive picker):
|
|
30
|
+
${Xe}`,$e=e=>!j(e)||fe(e).filter(e=>e!==`.git`).length===0,Z=e=>x(k(e,`packages/config/src/site.ts`)),et=e=>{let t=e,{root:n}=ue(t);for(;;){if(j(k(t,`bun.lock`))||j(k(t,`bun.lockb`)))return t;let e=k(t,`package.json`);if(j(e))try{if(JSON.parse(de(e,`utf8`)).workspaces)return t}catch{}if(t===n)return null;t=le(t)}},tt=async e=>{let{positionals:n,values:r}=J(Qe,{allowPositionals:!0,args:e,options:{canary:{type:`boolean`},db:{type:`boolean`},"dry-run":{type:`boolean`},help:{short:`h`,type:`boolean`},yes:{short:`y`,type:`boolean`},...Ze}});if(r.help){console.log(Qe);return}r[`dry-run`]||await Y(!!r.yes);let i=M()&&!r.yes,a=r.canary?`canary`:`main`,o=r,s=X.some(e=>o[e.flag]||o[`no-${e.flag}`]),c={...g};for(let e of X)c[e.value]=o[`no-${e.flag}`]?!1:o[e.flag]?!0:g[e.value];let l=n[0]??`.`,u=A(l),d=Z(u),f=!d&&!$e(u);if(!d&&!r[`dry-run`]){let e=et(f?process.cwd():le(u));if(e)throw Error(`Cannot scaffold inside an existing project (a workspace was found at ${e}). Run it in a fresh directory outside that project.`)}if(r[`dry-run`]||P(N(`https://zerostarter.dev`)),f){if(!i)throw Error(`Directory is not empty. Run it in an empty directory, or pass a project name: bunx zerostarter init <name>`);let e=await Ce(`What should we name your project?`);if(!e)throw Error(`No directory name provided.`);l=e}let p=A(l),m=se(p),ee={name:m},h=`--canary ignored: converting the existing checkout in place, so nothing is fetched.`,_=e=>X.filter(t=>e[t.value]).map(e=>e.value).join(`, `)||`none`;if(r[`dry-run`]){console.log(`bunx zerostarter init (dry run)`),console.log(` target: ${p}`),console.log(` name: ${m}`),console.log(` mode: ${Z(p)?`in place`:`fetch ${a}`}`),console.log(` features: ${_(c)}`),Z(p)&&r.canary&&console.log(` note: ${h}`);return}if(d&&i&&!await V(`Convert ${m} in place? This rewrites files and commits.`,!1)){I(`Aborted`);return}if(i&&!s){let e=new Set(await Se(`Which optional surfaces should this fork ship with?`,X.map(e=>({value:e.value,label:e.label,checked:g[e.value]}))));for(let t of X)c[t.value]=e.has(t.value)}if(Z(p))r.canary&&B(h);else{let e=r.canary?` (canary)`:``;await be(`Fetching the latest ZeroStarter${e}`,`Fetched the latest ZeroStarter${e}`,()=>Fe(p,a))}x(k(p,`.git`))||(await Ue(p),await q(p,`ci(init): scaffold from zerostarter`),await We(p,`main`)),await be(`Rebranding to ${m}`,`Rebranded to ${m}`,()=>ae(p,ee,c)),await K(p),await T(p),await q(p,`ci(init): re-baseline as ${m}`),De(p);let v=!1,y=await Te(),b=W(p),S=!1;if(b?r.db&&B(`--db ignored: POSTGRES_URL is already set in .env.`):S=r.db?!0:i?await V(`Provision a local Postgres database?`,y):y,S&&y)try{await Me(p),v=!0}catch(e){if(W(p))B(`Postgres is provisioned, but the migration failed; run bun run db:migrate.`);else{let t=e instanceof Error?e.message.trim():String(e);B(`Database setup failed; set POSTGRES_URL in .env yourself.`,t?t.split(`
|
|
31
|
+
`).filter(e=>e.trim()).slice(-5):[])}}else S&&B(`Docker isn't running, so the database wasn't provisioned. Set POSTGRES_URL in .env, or start Docker and re-run for automatic setup.`);R([`${t(`packages/config/src/site.ts`)} and ${t(`web/next/content`)}`,`to manage branding and blogs & docs respectively`].join(`
|
|
32
|
+
`),`Edit and make it yours`),ye(`${m} is ready`);let C=[];p!==process.cwd()&&C.push(t(`cd ${l}`)),W(p)||C.push(`set POSTGRES_URL in .env`),v||C.push(t(`bun run db:migrate`)),C.push(t(`bun run dev`)),R(C.join(`
|
|
33
|
+
`),`Next steps`),F(`Learn more ${N(`https://zerostarter.dev/docs`)}`)},nt=`Usage:
|
|
34
34
|
$ bunx zerostarter reinit [dir] [options]
|
|
35
35
|
|
|
36
36
|
Re-scaffold an existing git repo (default .) as a fresh ZeroStarter: delete every
|
|
@@ -40,8 +40,8 @@ branch; push when ready.
|
|
|
40
40
|
|
|
41
41
|
Options:
|
|
42
42
|
-y, --yes Skip the confirmation prompt
|
|
43
|
-
-h, --help Display help`,
|
|
44
|
-
`),`Next steps`),
|
|
43
|
+
-h, --help Display help`,rt=e=>[...e?[]:[`set POSTGRES_URL in .env`],t(`bun run db:migrate`),t(`bun run dev`),t(`git push`)],it=async e=>{let{positionals:t,values:n}=J(nt,{allowPositionals:!0,args:e,options:{help:{short:`h`,type:`boolean`},yes:{short:`y`,type:`boolean`}}});if(n.help){console.log(nt);return}await Y(!!n.yes);let i=A(t[0]??`.`),a=se(i),o=M()&&!n.yes;if(await Ve(i,`No git repository in ${i}. reinit re-scaffolds an existing repo; use init for a new project.`,`Working tree has uncommitted changes. Commit or stash them first; reinit deletes every tracked file.`),P(N(`https://zerostarter.dev`)),o&&!await V(`Delete every file in ${a} (keeping .git and .env*) and re-scaffold?`,!1)){I(`Aborted`);return}await He(i,r(`reinit failed; restored your committed files (deleted gitignored files, except .env*, are gone).`),async()=>{c(i),await Ie(i),z(`Fetched the latest ZeroStarter (kept .git and .env*)`),ae(i,{name:a}),z(`Rebranded to ${a}`),await K(i),await T(i),De(i),await q(i,`ci(reinit): re-baseline as ${a}`)}),R(rt(W(i)).join(`
|
|
44
|
+
`),`Next steps`),F(u(`${a} re-scaffolded; .git history, remote, and .env* files are intact`))},at=`Usage:
|
|
45
45
|
$ bunx zerostarter sync [dir] [options]
|
|
46
46
|
|
|
47
47
|
Re-baseline an existing fork (default .) on the latest ZeroStarter: a gitpick overlay
|
|
@@ -50,9 +50,9 @@ identity, favicon, and any skill or AGENTS.md you have edited are preserved. Req
|
|
|
50
50
|
you commit yourself.
|
|
51
51
|
|
|
52
52
|
Options:
|
|
53
|
-
-h, --help Display help`,it=async c=>{let{positionals:l,values:u}=J(
|
|
54
|
-
`),`Review the changes`),
|
|
55
|
-
${$}@${
|
|
53
|
+
-h, --help Display help`,ot=(e,t)=>{let n=e=>e.map(e=>`.agents/skills/${e}/SKILL.md`),r=e=>e.length===1?``:`s`;e.forkOwned.length>0&&z(`Left ${e.forkOwned.length} skill${r(e.forkOwned)} you own untouched:`,n(e.forkOwned)),e.customized.length>0&&(B(`Kept your edits to ${e.customized.length} skill${r(e.customized)}, so they did not take the update:`,n(e.customized)),z(`To take upstream's version instead, delete the skill directory and sync again.`)),t===`customized`&&z(`Kept your AGENTS.md, which you have edited, so it did not take the update. To take the starter's version instead, delete it, commit that on its own, and sync again.`),t===`forkOwned`&&z(`Kept your AGENTS.md. The starter now ships its full agent guide; to take it, delete AGENTS.md, commit that on its own, and sync again.`),e.unverified.length>0&&(B(`Updated ${e.unverified.length} skill${r(e.unverified)} with no sync record, so any edits of yours are in the diff rather than the file:`,n(e.unverified)),z(`Restore any with: git restore --source=HEAD -- .agents/skills/<name>/SKILL.md. Later syncs track them.`))},st=async c=>{let{positionals:l,values:u}=J(at,{allowPositionals:!0,args:c,options:{help:{short:`h`,type:`boolean`}}});if(u.help){console.log(at);return}await Y();let d=A(l[0]??`.`);await Ve(d,`No git repository in ${d}. Run sync inside an existing fork.`,`Working tree has uncommitted changes. Commit or stash them first so the sync lands as a reviewable diff.`),P(N(`https://zerostarter.dev`));let f=k(d,`package.json`),m=new Map(e(d).map(e=>[e,o(e)])),g=a(await Le()).preserve;g.length===0&&B(`No PRESERVE_ON_SYNC directive found; fork-owned files may be overwritten.`);let _=re(d),v=h(d),b=ie(d),C=p(),w=`absent`;await He(d,r(`Sync failed; rolled the working tree back to your last commit.`),async()=>{await Ie(d),te(d,_),s(k(d,`.gitpickignore`));for(let[e,t]of m)x(e)&&i(e,n(t,o(e),e===f));y(d),C=S(d,v);let e=ie(d);await ze(d,g),w=ee(d,{before:b,upstream:e})}),z(`Overlaid the latest ZeroStarter (content, public/marketing, and branding preserved)`),await K(d),await T(d),ne(d)&&B(`Your AGENTS.md has no skills-table markers, so the pre-commit hook that fills them fails.`,[`Add these two pairs under a ## Skills heading, then commit:`,`<!-- skills:custom --> <!-- /skills:custom -->`,`<!-- skills:vendored --> <!-- /skills:vendored -->`]),ot(C,w),R([`Starter files were updated (edits overwritten); your content, public/marketing, branding, and the skills and agent guide you own were preserved.`,r(`Review the diff and commit: git -C ${d} status`)].join(`
|
|
54
|
+
`),`Review the changes`),F(t(`Synced to the latest ZeroStarter`))},{author:Q,name:$,version:ct}=_e,lt=`Version:
|
|
55
|
+
${$}@${ct}
|
|
56
56
|
|
|
57
57
|
Go from zero to a production-ready SaaS, rebranded and ready to ship.
|
|
58
58
|
|
|
@@ -70,4 +70,4 @@ Options:
|
|
|
70
70
|
-h, --help Display help
|
|
71
71
|
|
|
72
72
|
Author:
|
|
73
|
-
${Q.name} <${Q.email}> (${
|
|
73
|
+
${Q.name} <${Q.email}> (${ve(Q.url)})`;(async()=>{try{let e=process.argv.slice(2),t=e[0],n=e.slice(1);switch(t){case`init`:return await tt(n);case`reinit`:return await it(n);case`sync`:return await st(n);case void 0:case`-h`:case`--help`:console.log(lt);return;case`-v`:case`--version`:console.log(`${$}@${ct}`);return;default:console.error(d(`Unknown command: ${t}\n`)),console.log(lt),process.exit(1)}}catch(e){C(e),process.exit(1)}})();export{};
|