zerostarter 0.1.9 → 0.1.11

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.
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
- import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,p as c,r as l,s as u,t as d,u as f}from"../convert-qIUh5kib.mjs";import{basename as p,delimiter as m,dirname as h,join as g,parse as _,resolve as v}from"node:path";import{existsSync as y,readFileSync as b,readdirSync as ee}from"node:fs";import{spawn as x}from"node:child_process";import{access as te}from"node:fs/promises";import{createInterface as S}from"node:readline/promises";import{randomBytes as C}from"node:crypto";import{parseArgs as ne}from"node:util";import{homedir as w}from"node:os";const T=(e,t,n=process.stdout)=>r=>n.isTTY?`\x1b[${e}m${r}\x1b[${t}m`:r,E=T(`36`,`39`),D=T(`32`,`39`),O=T(`33`,`39`),k=T(`90`,`39`),A=T(`2`,`22`),j=T(`31`,`39`,process.stderr),re=T(`2`,`22`,process.stderr),M=T(`38;5;208`,`39`),N=[`◇`,`◆`],P=(e,t)=>{let n=(e%N.length+N.length)%N.length;return`${E(N[n])} ${t}`},F={barStart:`┌`,bar:`│`,barEnd:`└`,active:`◆`,submit:`◇`,radioOn:`●`,radioOff:`○`,checkboxOn:`◼`,checkboxOff:`◻`,warn:`▲`,error:`■`,barH:`─`,cornerTR:`╮`,connectL:`├`,cornerBL:`╰`,cornerBR:`╯`};var ie=class extends Error{constructor(...e){super(...e),this.name=`SubprocessError`,this.stdout=``,this.stderr=``}};const ae=[`.exe`,`.com`],I=e=>e.replaceAll(/([()\][%!^"`<>&|;, *?])/g,`^$1`),oe=e=>I(I(`"${e.replaceAll(/(\\*)"/g,`$1$1\\"`).replace(/(\\*)$/,`$1$1`)}"`)),se=async(e,t,n)=>{if(ae.some(t=>e.toLowerCase().endsWith(t)))return!0;let r=(n.PATH||n.Path||``).split(m).filter(Boolean).map(e=>e.replace(/^"(.*)"$/,`$1`));try{return await Promise.any([t,...r].flatMap(t=>ae.map(n=>te(`${v(t,e)}${n}`)))),!0}catch{return!1}},ce=async(e,t,n,r=process.platform===`win32`)=>{let i=n.cwd?String(n.cwd):`.`,a=n.env||process.env;return r&&!n.shell&&!await se(e,i,a)?[I(e),t.map(oe),{...n,shell:!0}]:[e,t,n]},L=async(e,t,n,r)=>{let i=[e,...t].join(` `),[a,o,s]=await ce(e,t,n);s.shell&&o.length>0&&(a=[a,...o].join(` `),o=[]);let c=x(a,o,s),l=``,u=``;return new Promise((e,t)=>{let n=(e,n,r)=>{let i=new ie(e,r?{cause:r}:void 0);i.stdout=l,i.stderr=u,i.exitCode=n,t(i)},a=e=>{e.code!==`ERR_STREAM_PREMATURE_CLOSE`&&e.code!==`EPIPE`&&n(`Command failed: ${i}`,void 0,e)};c.stdout&&(c.stdout.setEncoding(`utf8`),c.stdout.on(`data`,e=>{l+=e,r?.(e)}),c.stdout.on(`error`,a)),c.stderr&&(c.stderr.setEncoding(`utf8`),c.stderr.on(`data`,e=>{u+=e,r?.(e)}),c.stderr.on(`error`,a)),c.on(`error`,e=>n(`Command failed: ${i}`,void 0,e)),c.on(`close`,(t,r)=>{if(r)return n(`Command was terminated with ${r}: ${i}`);if(t!==0)return n(`Command failed with exit code ${t}: ${i}`,t??void 0);e({stdout:l,stderr:u})})})},R=async(e,t,n)=>{let{stdout:r}=await L(e,t,{cwd:n,stdio:[`ignore`,`pipe`,`pipe`]});return r},le=async(e,t,n)=>{await L(e,t,{cwd:n,stdio:`inherit`})},z=async(e,t)=>{try{return await L(e,t,{stdio:`ignore`}),!0}catch{return!1}},ue=RegExp(`\x1B\\[[0-9;?]*[a-zA-Z]`,`g`),de=e=>e.replace(ue,``),fe=new WeakSet,pe=e=>{if(process.stderr.write(`\n ${j(e instanceof Error?e.message:String(e))}\n`),!(e instanceof ie)||fe.has(e))return;let t=(e.stderr||e.stdout||``).trim();if(!t)return;let n=de(t).split(`
3
- `).map(e=>e.trimEnd()).filter(Boolean).slice(-12);for(let e of n)process.stderr.write(` ${re(e)}\n`)},me=async(e,t,n)=>{let r=process.stdout,i=n.label??``;if(!r.isTTY){i&&r.write(` ${E(F.active)} ${i}\n`),await le(e,t,n.cwd);return}let a=n.lines??3,o=[],s=0,c=0,l=``,u=``,d=()=>(r.columns||80)-1,f=e=>{r.write(e?`\x1B[?7h`:`\x1B[?7l`)},p=()=>{c>0&&(r.write(`[${c}A`),c=0)},m=()=>{p();let e=0;r.write(` ${P(s,i)}\n`),e++;for(let t of o.slice(-a))r.write(` ${k(F.bar)} ${A(t.slice(0,Math.max(0,d()-5)))}\n`),e++;c=e},h=e=>{u+=e,l+=e;let t=l.split(`
4
- `);l=t.pop()??``;for(let e of t)o.push(de(e).replace(/\r/g,``).replace(/\t/g,` `).trimEnd()),m()};m(),f(!1);let g=()=>{f(!0),process.exit(130)};process.once(`SIGINT`,g);let _=setInterval(()=>{s+=1,m()},400),v=()=>{clearInterval(_),process.removeListener(`SIGINT`,g)};try{await L(e,t,{cwd:n.cwd,stdio:[`ignore`,`pipe`,`pipe`]},h)}catch(e){throw v(),p(),f(!0),r.write(u),e&&typeof e==`object`&&fe.add(e),e}v(),p(),f(!0),r.write(` ${E(F.active)} ${n.done??i}\n`);for(let e of o.slice(-a))r.write(` ${k(F.bar)} ${A(e.slice(0,Math.max(0,d()-5)))}\n`)};var he={name:`zerostarter`,version:`0.1.9`,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`,test:`bun test`},devDependencies:{"@packages/config":`workspace:*`,"@types/bun":`catalog:`,"@types/node":`catalog:`,tsdown:`catalog:`,typescript:`catalog:`}};const B=()=>!!(process.stdin.isTTY&&process.stdout.isTTY),ge=(e,t=e)=>process.stdout.isTTY?`\x1b]8;;${e}\x07${t}\x1b]8;;\x07`:e,V=e=>ge(e,E(e)),H=e=>{process.stdout.write(`\n ${k(F.barStart)} ${e}\n ${k(F.bar)}\n`)},U=e=>{process.stdout.write(` ${k(F.bar)}\n ${k(F.barEnd)} ${e}\n`)},W=(e=`Cancelled`)=>{process.stdout.write(` ${k(F.barEnd)} ${j(e)}\n`)},G=e=>e.replace(RegExp(`\x1B\\[[0-9;?]*[a-zA-Z]`,`g`),``).replace(RegExp(`\x1B\\]8;;.*?\\x07`,`g`),``).length,K=(e,t=``,n=!1)=>{let r=`\n${e}\n`.split(`
5
- `),i=G(t),a=r.reduce((e,t)=>Math.max(e,G(t)),i),o=Math.max(a,54)+2,s=r.map(e=>` ${k(F.bar)} ${e}${` `.repeat(o-G(e))}${k(F.bar)}`).join(`
6
- `),c=n?F.cornerBL:F.connectL;process.stdout.write(` ${E(F.active)} ${t} ${k(F.barH.repeat(Math.max(o-i-1,1))+F.cornerTR)}\n${s}\n ${k(c+F.barH.repeat(o+2)+F.cornerBR)}\n`)},q=(e,t=[])=>{process.stdout.write(` ${E(F.active)} ${e}\n`);for(let e of t)process.stdout.write(` ${k(F.bar)} ${e}\n`)},_e=e=>{process.stdout.write(` ${D(F.active)} ${D(e)}\n`)},J=(e,t=[])=>{process.stdout.write(` ${O(F.warn)} ${O(e)}\n`);for(let e of t)process.stdout.write(` ${k(F.bar)} ${O(e)}\n`)},ve=async(e,t,n)=>{let r=process.stdout,i=null;if(r.isTTY){let t=0;r.write(` ${P(0,e)}`),i=setInterval(()=>{t+=1,r.write(`\r\x1b[K ${P(t,e)}`)},400)}try{let e=await n();return i&&clearInterval(i),r.write(r.isTTY?`\r\x1b[K ${E(F.active)} ${t}\n`:` ${E(F.active)} ${t}\n`),e}catch(e){throw i&&clearInterval(i),r.isTTY&&r.write(`\r\x1B[K`),e}},ye=e=>{let t=e?`${D(F.radioOn)} Yes`:A(`${F.radioOff} Yes`),n=e?A(`${F.radioOff} No`):`${D(F.radioOn)} No`;return` ${k(F.bar)} ${t} ${A(`/`)} ${n}`},Y=async(e,t=!0)=>{let n=process.stdout;return B()?new Promise(r=>{let i=t,a=process.stdin,o=Math.max(1,Math.ceil((5+G(e))/(n.columns||80)));n.write(` ${E(F.submit)} ${e}\n`),n.write(ye(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(` ${E(F.submit)} ${A(e)}\n`),W(),process.exit(130)):t===`\r`||t===`
7
- `?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${ye(i)}`))}a.on(`data`,u)}):(n.write(` ${E(F.active)} ${e} ${A(t?`Yes`:`No`)}\n`),t)},be=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 B()?new Promise(a=>{let o=process.stdin,s=0,c=e=>{let n=t[e],i=r.has(n.value)?D(F.checkboxOn):A(F.checkboxOff),a=e===s?n.label:A(n.label);return` ${k(F.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(` ${E(F.submit)} ${e}\n`),l(!0),o.setRawMode(!0),o.resume(),o.setEncoding(`utf8`);let u=()=>{o.setRawMode(!1),o.pause(),o.removeListener(`data`,d)};function d(o){if(o===``)u(),n.write(`\x1b[${t.length+1}A\r\x1b[0J ${E(F.submit)} ${A(e)}\n`),W(),process.exit(130);else if(o===`\r`||o===`
8
- `)u(),n.write(`\x1b[${t.length+1}A\r\x1b[0J ${E(F.submit)} ${e} ${A(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`,d)}):(n.write(` ${E(F.submit)} ${e} ${A(i())}\n`),[...r])},xe=async(e,t=``)=>{process.stdout.write(` ${E(F.submit)} ${e}${t?` ${A(`(${t})`)}`:``}\n`);let n=S({input:process.stdin,output:process.stdout});try{return(await n.question(` ${k(F.bar)} `)).trim()||t}finally{n.close()}},Se=`pglaunch@5.5.7`,Ce=async()=>z(`docker`,[`info`]),we=e=>{let r=g(e,`.env`);if(!s(r)){let i=g(e,`.env.example`);n(r,s(i)?t(i):``)}return r},Te=(e,n)=>{let r=`${n}=`,i=t(e).split(`
9
- `).find(e=>e.startsWith(r));return i?i.slice(r.length).trim():``},Ee=(e,r,i)=>{let a=`${r}=`,o=t(e).split(`
10
- `),s=o.findIndex(e=>e.startsWith(a));if(s>=0)o[s]=`${a}${i}`;else{for(;o.length&&o[o.length-1]===``;)o.pop();o.push(`${a}${i}`,``)}n(e,o.join(`
11
- `))},De=e=>{let t=we(e);Te(t,`BETTER_AUTH_SECRET`)||Ee(t,`BETTER_AUTH_SECRET`,C(32).toString(`base64`)),Te(t,`AGENT_SIGNIN_ENABLED`)||Ee(t,`AGENT_SIGNIN_ENABLED`,`true`)},X=e=>{let t=g(e,`.env`);return s(t)&&Te(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`,Se,`-k`,`-c`]:[`--bun`,Se,`-k`],r;try{r=await R(`bunx`,n,e)}catch(e){let t=e;r=[t.stdout,t.stderr].filter(Boolean).join(`
12
- `)}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 z(`docker`,[`exec`,e,`pg_isready`,`-U`,`postgres`]))return;await Ae(1e3)}},Me=async e=>{let t=we(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`);Ee(t,`POSTGRES_URL`,r.launch.url),await je(r.launch.container),await me(`bun`,[`run`,`db:migrate`],{cwd:e,label:`Provisioning a local Postgres database`,done:`Provisioned a local Postgres database`})},Ne=async e=>{await me(`bun`,[`install`],{cwd:e,label:`Installing dependencies`,done:`Installed dependencies`})},Pe=async()=>{if(!await z(`bun`,[`--version`]))throw Error(`bun is not on PATH`)},Fe=async(e=Pe,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}},Ie=async(e,t=`main`)=>{await R(`bunx`,[`--bun`,`gitpick@6.0.0`,`https://github.com/nrjdalal/zerostarter/tree/${t}`,e])},Le=async(e,t=`main`)=>{await R(`bunx`,[`--bun`,`gitpick@6.0.0`,`https://github.com/nrjdalal/zerostarter/tree/${t}`,e,`-o`])},Re=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()},ze=async e=>(await R(`git`,[`status`,`--porcelain`],e)).trim()===``,Be=async(e,t)=>{for(let n of t)try{await R(`git`,[`checkout`,`--`,n],e),await R(`git`,[`clean`,`-fd`,`--`,n],e)}catch{}},Ve=async e=>{await R(`git`,[`reset`,`--hard`,`HEAD`],e),await R(`git`,[`clean`,`-fd`],e)},He=async(e,t,n)=>{if(!s(g(e,`.git`)))throw Error(t);if(!await ze(e))throw Error(n)},Ue=async(e,t,n)=>{try{await n()}catch(n){throw await Ve(e),console.log(t),n}},We=async e=>{await R(`git`,[`init`,`-q`,`-b`,`canary`],e)},Ge=async(e,t)=>{await R(`git`,[`branch`,t],e)},Ke=async(e,t)=>{await R(`git`,[`add`,`-A`],e);try{await R(`git`,[`commit`,`--no-verify`,`-q`,`-m`,t],e)}catch{}},qe=(e,t)=>{try{return ne(t)}catch(t){process.stderr.write(`${j(t instanceof Error?t.message:String(t))}\n\n`),process.stdout.write(`${e}\n`),process.exit(1)}},Je=(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`,Ye=(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`]},Xe=(e=process.argv.slice(2))=>[`zerostarter`,...e].join(` `),Ze=()=>g(process.env.BUN_INSTALL||g(w(),`.bun`),`bin`),Qe=async(e=!1)=>{if(await Fe())return;let t=Je(),n=`bunx --bun ${Xe()}`;if(console.error(j(`Seems like you are using ${t===`unknown`?`npx/pnpx`:t} or Windows, try using:`)),console.error(M(` ${n}`)),console.error(``),e||B()&&await Y(`Or install bun now and continue?`,!0)){let{cmd:e,args:t}=Ye();console.error(`Installing bun from https://bun.sh/install ...`);try{if(await le(e,t),process.env.PATH=`${Ze()}${m}${process.env.PATH||``}`,await Fe())return;console.error(j(`
2
+ import{a as e,c as t,d as n,f as r,i,l as a,m as o,n as s,o as c,p as l,r as u,s as d,t as f,u as p}from"../convert-Crk8STXb.mjs";import{basename as m,delimiter as h,dirname as g,join as _,parse as v,resolve as y}from"node:path";import{existsSync as b,readFileSync as ee,readdirSync as x}from"node:fs";import{spawn as te}from"node:child_process";import{access as ne}from"node:fs/promises";import{createInterface as S}from"node:readline/promises";import{randomBytes as re}from"node:crypto";import{parseArgs as C}from"node:util";import{homedir as w}from"node:os";const T=(e,t,n=process.stdout)=>r=>n.isTTY?`\x1b[${e}m${r}\x1b[${t}m`:r,E=T(`36`,`39`),D=T(`32`,`39`),O=T(`33`,`39`),k=T(`90`,`39`),A=T(`2`,`22`),j=T(`31`,`39`,process.stderr),ie=T(`2`,`22`,process.stderr),M=T(`38;5;208`,`39`),N=[`◇`,`◆`],P=(e,t)=>{let n=(e%N.length+N.length)%N.length;return`${E(N[n])} ${t}`},F={barStart:`┌`,bar:`│`,barEnd:`└`,active:`◆`,submit:`◇`,radioOn:`●`,radioOff:`○`,checkboxOn:`◼`,checkboxOff:`◻`,warn:`▲`,error:`■`,barH:`─`,cornerTR:`╮`,connectL:`├`,cornerBL:`╰`,cornerBR:`╯`};var ae=class extends Error{constructor(...e){super(...e),this.name=`SubprocessError`,this.stdout=``,this.stderr=``}};const oe=[`.exe`,`.com`],se=e=>e.replaceAll(/([()\][%!^"`<>&|;, *?])/g,`^$1`),ce=e=>se(se(`"${e.replaceAll(/(\\*)"/g,`$1$1\\"`).replace(/(\\*)$/,`$1$1`)}"`)),le=async(e,t,n)=>{if(oe.some(t=>e.toLowerCase().endsWith(t)))return!0;let r=(n.PATH||n.Path||``).split(h).filter(Boolean).map(e=>e.replace(/^"(.*)"$/,`$1`));try{return await Promise.any([t,...r].flatMap(t=>oe.map(n=>ne(`${y(t,e)}${n}`)))),!0}catch{return!1}},ue=async(e,t,n,r=process.platform===`win32`)=>{let i=n.cwd?String(n.cwd):`.`,a=n.env||process.env;return r&&!n.shell&&!await le(e,i,a)?[se(e),t.map(ce),{...n,shell:!0}]:[e,t,n]},I=async(e,t,n,r)=>{let i=[e,...t].join(` `),[a,o,s]=await ue(e,t,n);s.shell&&o.length>0&&(a=[a,...o].join(` `),o=[]);let c=te(a,o,s),l=``,u=``;return new Promise((e,t)=>{let n=(e,n,r)=>{let i=new ae(e,r?{cause:r}:void 0);i.stdout=l,i.stderr=u,i.exitCode=n,t(i)},a=e=>{e.code!==`ERR_STREAM_PREMATURE_CLOSE`&&e.code!==`EPIPE`&&n(`Command failed: ${i}`,void 0,e)};c.stdout&&(c.stdout.setEncoding(`utf8`),c.stdout.on(`data`,e=>{l+=e,r?.(e)}),c.stdout.on(`error`,a)),c.stderr&&(c.stderr.setEncoding(`utf8`),c.stderr.on(`data`,e=>{u+=e,r?.(e)}),c.stderr.on(`error`,a)),c.on(`error`,e=>n(`Command failed: ${i}`,void 0,e)),c.on(`close`,(t,r)=>{if(r)return n(`Command was terminated with ${r}: ${i}`);if(t!==0)return n(`Command failed with exit code ${t}: ${i}`,t??void 0);e({stdout:l,stderr:u})})})},L=async(e,t,n)=>{let{stdout:r}=await I(e,t,{cwd:n,stdio:[`ignore`,`pipe`,`pipe`]});return r},de=async(e,t,n)=>{await I(e,t,{cwd:n,stdio:`inherit`})},R=async(e,t)=>{try{return await I(e,t,{stdio:`ignore`}),!0}catch{return!1}},fe=RegExp(`\x1B\\[[0-9;?]*[a-zA-Z]`,`g`),pe=e=>e.replace(fe,``),me=new WeakSet,he=e=>{if(process.stderr.write(`\n ${j(e instanceof Error?e.message:String(e))}\n`),!(e instanceof ae)||me.has(e))return;let t=(e.stderr||e.stdout||``).trim();if(!t)return;let n=pe(t).split(`
3
+ `).map(e=>e.trimEnd()).filter(Boolean).slice(-12);for(let e of n)process.stderr.write(` ${ie(e)}\n`)},ge=async(e,t,n)=>{let r=process.stdout,i=n.label??``;if(!r.isTTY){i&&r.write(` ${E(F.active)} ${i}\n`),await de(e,t,n.cwd);return}let a=n.lines??3,o=[],s=0,c=0,l=``,u=``,d=()=>(r.columns||80)-1,f=e=>{r.write(e?`\x1B[?7h`:`\x1B[?7l`)},p=()=>{c>0&&(r.write(`[${c}A`),c=0)},m=()=>{p();let e=0;r.write(` ${P(s,i)}\n`),e++;for(let t of o.slice(-a))r.write(` ${k(F.bar)} ${A(t.slice(0,Math.max(0,d()-5)))}\n`),e++;c=e},h=e=>{u+=e,l+=e;let t=l.split(`
4
+ `);l=t.pop()??``;for(let e of t)o.push(pe(e).replace(/\r/g,``).replace(/\t/g,` `).trimEnd()),m()};m(),f(!1);let g=()=>{f(!0),process.exit(130)};process.once(`SIGINT`,g);let _=setInterval(()=>{s+=1,m()},400),v=()=>{clearInterval(_),process.removeListener(`SIGINT`,g)};try{await I(e,t,{cwd:n.cwd,stdio:[`ignore`,`pipe`,`pipe`]},h)}catch(e){throw v(),p(),f(!0),r.write(u),e&&typeof e==`object`&&me.add(e),e}v(),p(),f(!0),r.write(` ${E(F.active)} ${n.done??i}\n`);for(let e of o.slice(-a))r.write(` ${k(F.bar)} ${A(e.slice(0,Math.max(0,d()-5)))}\n`)};var _e={name:`zerostarter`,version:`0.1.11`,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`,test:`bun test`},devDependencies:{"@packages/config":`workspace:*`,"@types/bun":`catalog:`,"@types/node":`catalog:`,tsdown:`catalog:`,typescript:`catalog:`}};const z=()=>!!(process.stdin.isTTY&&process.stdout.isTTY),ve=(e,t=e)=>process.stdout.isTTY?`\x1b]8;;${e}\x07${t}\x1b]8;;\x07`:e,B=e=>ve(e,E(e)),V=e=>{process.stdout.write(`\n ${k(F.barStart)} ${e}\n ${k(F.bar)}\n`)},H=e=>{process.stdout.write(` ${k(F.bar)}\n ${k(F.barEnd)} ${e}\n`)},U=(e=`Cancelled`)=>{process.stdout.write(` ${k(F.barEnd)} ${j(e)}\n`)},W=e=>e.replace(RegExp(`\x1B\\[[0-9;?]*[a-zA-Z]`,`g`),``).replace(RegExp(`\x1B\\]8;;.*?\\x07`,`g`),``).length,G=(e,t=``,n=!1)=>{let r=`\n${e}\n`.split(`
5
+ `),i=W(t),a=r.reduce((e,t)=>Math.max(e,W(t)),i),o=Math.max(a,54)+2,s=r.map(e=>` ${k(F.bar)} ${e}${` `.repeat(o-W(e))}${k(F.bar)}`).join(`
6
+ `),c=n?F.cornerBL:F.connectL;process.stdout.write(` ${E(F.active)} ${t} ${k(F.barH.repeat(Math.max(o-i-1,1))+F.cornerTR)}\n${s}\n ${k(c+F.barH.repeat(o+2)+F.cornerBR)}\n`)},K=(e,t=[])=>{process.stdout.write(` ${E(F.active)} ${e}\n`);for(let e of t)process.stdout.write(` ${k(F.bar)} ${e}\n`)},ye=e=>{process.stdout.write(` ${D(F.active)} ${D(e)}\n`)},q=(e,t=[])=>{process.stdout.write(` ${O(F.warn)} ${O(e)}\n`);for(let e of t)process.stdout.write(` ${k(F.bar)} ${O(e)}\n`)},be=async(e,t,n)=>{let r=process.stdout,i=null;if(r.isTTY){let t=0;r.write(` ${P(0,e)}`),i=setInterval(()=>{t+=1,r.write(`\r\x1b[K ${P(t,e)}`)},400)}try{let e=await n();return i&&clearInterval(i),r.write(r.isTTY?`\r\x1b[K ${E(F.active)} ${t}\n`:` ${E(F.active)} ${t}\n`),e}catch(e){throw i&&clearInterval(i),r.isTTY&&r.write(`\r\x1B[K`),e}},xe=e=>{let t=e?`${D(F.radioOn)} Yes`:A(`${F.radioOff} Yes`),n=e?A(`${F.radioOff} No`):`${D(F.radioOn)} No`;return` ${k(F.bar)} ${t} ${A(`/`)} ${n}`},J=async(e,t=!0)=>{let n=process.stdout;return z()?new Promise(r=>{let i=t,a=process.stdin,o=Math.max(1,Math.ceil((5+W(e))/(n.columns||80)));n.write(` ${E(F.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(` ${E(F.submit)} ${A(e)}\n`),U(),process.exit(130)):t===`\r`||t===`
7
+ `?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(` ${E(F.active)} ${e} ${A(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 z()?new Promise(a=>{let o=process.stdin,s=0,c=e=>{let n=t[e],i=r.has(n.value)?D(F.checkboxOn):A(F.checkboxOff),a=e===s?n.label:A(n.label);return` ${k(F.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(` ${E(F.submit)} ${e}\n`),l(!0),o.setRawMode(!0),o.resume(),o.setEncoding(`utf8`);let u=()=>{o.setRawMode(!1),o.pause(),o.removeListener(`data`,d)};function d(o){if(o===``)u(),n.write(`\x1b[${t.length+1}A\r\x1b[0J ${E(F.submit)} ${A(e)}\n`),U(),process.exit(130);else if(o===`\r`||o===`
8
+ `)u(),n.write(`\x1b[${t.length+1}A\r\x1b[0J ${E(F.submit)} ${e} ${A(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`,d)}):(n.write(` ${E(F.submit)} ${e} ${A(i())}\n`),[...r])},Ce=async(e,t=``)=>{process.stdout.write(` ${E(F.submit)} ${e}${t?` ${A(`(${t})`)}`:``}\n`);let n=S({input:process.stdin,output:process.stdout});try{return(await n.question(` ${k(F.bar)} `)).trim()||t}finally{n.close()}},we=`pglaunch@5.5.7`,Te=async()=>R(`docker`,[`info`]),Ee=e=>{let t=_(e,`.env`);if(!d(t)){let n=_(e,`.env.example`);r(t,d(n)?a(n):``)}return t},De=(e,t)=>{let n=`${t}=`,r=a(e).split(`
9
+ `).find(e=>e.startsWith(n));return r?r.slice(n.length).trim():``},Oe=(e,t,n)=>{let i=`${t}=`,o=a(e).split(`
10
+ `),s=o.findIndex(e=>e.startsWith(i));if(s>=0)o[s]=`${i}${n}`;else{for(;o.length&&o[o.length-1]===``;)o.pop();o.push(`${i}${n}`,``)}r(e,o.join(`
11
+ `))},ke=e=>{let t=Ee(e);De(t,`BETTER_AUTH_SECRET`)||Oe(t,`BETTER_AUTH_SECRET`,re(32).toString(`base64`)),De(t,`AGENT_SIGNIN_ENABLED`)||Oe(t,`AGENT_SIGNIN_ENABLED`,`true`)},Y=e=>{let t=_(e,`.env`);return d(t)&&De(t,`POSTGRES_URL`)!==``},Ae=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]:``}},je=async(e,t)=>{let n=t?[`--bun`,we,`-k`,`-c`]:[`--bun`,we,`-k`],r;try{r=await L(`bunx`,n,e)}catch(e){let t=e;r=[t.stdout,t.stderr].filter(Boolean).join(`
12
+ `)}return{launch:Ae(r),out:r}},Me=e=>new Promise(t=>setTimeout(t,e)),Ne=async e=>{if(e)for(let t=0;t<30;t++){if(await R(`docker`,[`exec`,e,`pg_isready`,`-U`,`postgres`]))return;await Me(1e3)}},Pe=async e=>{let t=Ee(e),n=await je(e,!1),r=n.launch?n:await je(e,!0);if(!r.launch)throw Error(r.out.trim()||`pglaunch did not print a connection URL`);Oe(t,`POSTGRES_URL`,r.launch.url),await Ne(r.launch.container),await ge(`bun`,[`run`,`db:migrate`],{cwd:e,label:`Provisioning a local Postgres database`,done:`Provisioned a local Postgres database`})},Fe=async e=>{await ge(`bun`,[`install`],{cwd:e,label:`Installing dependencies`,done:`Installed dependencies`})},Ie=async()=>{if(!await R(`bun`,[`--version`]))throw Error(`bun is not on PATH`)},Le=async(e=Ie,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}},Re=async(e,t=`main`)=>{await L(`bunx`,[`--bun`,`gitpick@6.0.0`,`https://github.com/nrjdalal/zerostarter/tree/${t}`,e])},ze=async(e,t=`main`)=>{await L(`bunx`,[`--bun`,`gitpick@6.0.0`,`https://github.com/nrjdalal/zerostarter/tree/${t}`,e,`-o`])},Be=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()},Ve=async e=>(await L(`git`,[`status`,`--porcelain`],e)).trim()===``,He=async(e,t)=>{for(let n of t)try{await L(`git`,[`checkout`,`--`,n],e),await L(`git`,[`clean`,`-fd`,`--`,n],e)}catch{}},Ue=async e=>{await L(`git`,[`reset`,`--hard`,`HEAD`],e),await L(`git`,[`clean`,`-fd`],e)},We=async(e,t,n)=>{if(!d(_(e,`.git`)))throw Error(t);if(!await Ve(e))throw Error(n)},Ge=async(e,t,n)=>{try{await n()}catch(n){throw await Ue(e),console.log(t),n}},Ke=async e=>{await L(`git`,[`init`,`-q`,`-b`,`canary`],e)},qe=async(e,t)=>{await L(`git`,[`branch`,t],e)},X=async(e,t)=>{await L(`git`,[`add`,`-A`],e);try{await L(`git`,[`commit`,`--no-verify`,`-q`,`-m`,t],e)}catch{}},Je=(e,t)=>{try{return C(t)}catch(t){process.stderr.write(`${j(t instanceof Error?t.message:String(t))}\n\n`),process.stdout.write(`${e}\n`),process.exit(1)}},Ye=(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`,Xe=(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`]},Ze=(e=process.argv.slice(2))=>[`zerostarter`,...e].join(` `),Qe=()=>_(process.env.BUN_INSTALL||_(w(),`.bun`),`bin`),$e=async(e=!1)=>{if(await Le())return;let t=Ye(),n=`bunx --bun ${Ze()}`;if(console.error(j(`Seems like you are using ${t===`unknown`?`npx/pnpx`:t} or Windows, try using:`)),console.error(M(` ${n}`)),console.error(``),e||z()&&await J(`Or install bun now and continue?`,!0)){let{cmd:e,args:t}=Xe();console.error(`Installing bun from https://bun.sh/install ...`);try{if(await de(e,t),process.env.PATH=`${Qe()}${h}${process.env.PATH||``}`,await Le())return;console.error(j(`
13
13
  bun is installed but isn't on this shell's PATH yet. Open a new terminal and re-run:`)),console.error(M(` ${n}`))}catch{console.error(j(`
14
- Could not install bun. Install it from https://bun.sh, then re-run:`)),console.error(M(` ${n}`))}}process.exit(1)},Z=[{value:`apiDocs`,flag:`api-docs`,label:`API docs`},{value:`blog`,flag:`blog`,label:`Blog`},{value:`docs`,flag:`docs`,label:`Docs`},{value:`internalDocs`,flag:`internal-docs`,label:`Internal (console) docs`},{value:`waitlist`,flag:`waitlist`,label:`Waitlist (else a plain landing home)`}],$e=`Usage:
14
+ Could not install bun. Install it from https://bun.sh, then re-run:`)),console.error(M(` ${n}`))}}process.exit(1)},Z=[{value:`apiDocs`,flag:`api-docs`,label:`API docs`},{value:`blog`,flag:`blog`,label:`Blog`},{value:`docs`,flag:`docs`,label:`Docs`},{value:`internalDocs`,flag:`internal-docs`,label:`Internal (console) docs`},{value:`waitlist`,flag:`waitlist`,label:`Waitlist (else a plain landing home)`}],et=`Usage:
15
15
  $ bunx zerostarter init [dir] [options]
16
16
 
17
17
  Scaffold ZeroStarter into dir (default .) as a fresh product. The author's
@@ -32,10 +32,10 @@ Features (default on, except the waitlist; pass any flag to skip the interactive
32
32
  --blog, --no-blog The /blog
33
33
  --docs, --no-docs The /docs
34
34
  --internal-docs, --no-internal-docs The /console/docs internal docs
35
- --waitlist, --no-waitlist The /waitlist (off leaves a plain landing home)`,et=e=>!y(e)||ee(e).filter(e=>e!==`.git`).length===0,Q=e=>s(g(e,`packages/config/src/site.ts`)),tt=e=>{let t=e,{root:n}=_(t);for(;;){if(y(g(t,`bun.lock`))||y(g(t,`bun.lockb`)))return t;let e=g(t,`package.json`);if(y(e))try{if(JSON.parse(b(e,`utf8`)).workspaces)return t}catch{}if(t===n)return null;t=h(t)}},nt=async e=>{let{positionals:t,values:n}=qe($e,{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`},"api-docs":{type:`boolean`},"no-api-docs":{type:`boolean`},blog:{type:`boolean`},"no-blog":{type:`boolean`},docs:{type:`boolean`},"no-docs":{type:`boolean`},"internal-docs":{type:`boolean`},"no-internal-docs":{type:`boolean`},waitlist:{type:`boolean`},"no-waitlist":{type:`boolean`}}});if(n.help){console.log($e);return}n[`dry-run`]||await Qe(!!n.yes);let r=B()&&!n.yes,i=n.canary?`canary`:`main`,a=n,o=Z.some(e=>a[e.flag]||a[`no-${e.flag}`]),c={...l};for(let e of Z)c[e.value]=a[`no-${e.flag}`]?!1:a[e.flag]?!0:l[e.value];let u=t[0]??`.`,f=v(u),m=Q(f),_=!m&&!et(f);if(!m&&!n[`dry-run`]){let e=tt(_?process.cwd():h(f));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(n[`dry-run`]||H(V(`https://zerostarter.dev`)),_){if(!r)throw Error(`Directory is not empty. Run it in an empty directory, or pass a project name: bunx zerostarter init <name>`);let e=await xe(`What should we name your project?`);if(!e)throw Error(`No directory name provided.`);u=e}let y=v(u),b=p(y),ee={name:b},x=`--canary ignored: converting the existing checkout in place, so nothing is fetched.`,te=e=>Z.filter(t=>e[t.value]).map(e=>e.value).join(`, `)||`none`;if(n[`dry-run`]){console.log(`bunx zerostarter init (dry run)`),console.log(` target: ${y}`),console.log(` name: ${b}`),console.log(` mode: ${Q(y)?`in place`:`fetch ${i}`}`),console.log(` features: ${te(c)}`),Q(y)&&n.canary&&console.log(` note: ${x}`);return}if(m&&r&&!await Y(`Convert ${b} in place? This rewrites files and commits.`,!1)){W(`Aborted`);return}if(r&&!o){let e=new Set(await be(`Which optional surfaces should this fork ship with?`,Z.map(e=>({value:e.value,label:e.label,checked:l[e.value]}))));for(let t of Z)c[t.value]=e.has(t.value)}if(Q(y))n.canary&&J(x);else{let e=n.canary?` (canary)`:``;await ve(`Fetching the latest ZeroStarter${e}`,`Fetched the latest ZeroStarter${e}`,()=>Ie(y,i))}s(g(y,`.git`))||(await We(y),await Ke(y,`ci(init): scaffold from zerostarter`),await Ge(y,`main`)),await ve(`Rebranding to ${b}`,`Rebranded to ${b}`,()=>d(y,ee,c)),await Ne(y),await Ke(y,`ci(init): re-baseline as ${b}`),De(y);let S=!1,C=await Ce(),ne=X(y),w=!1;if(ne?n.db&&J(`--db ignored: POSTGRES_URL is already set in .env.`):w=n.db?!0:r?await Y(`Provision a local Postgres database?`,C):C,w&&C)try{await Me(y),S=!0}catch(e){if(X(y))J(`Postgres is provisioned, but the migration failed; run bun run db:migrate.`);else{let t=e instanceof Error?e.message.trim():String(e);J(`Database setup failed; set POSTGRES_URL in .env yourself.`,t?t.split(`
36
- `).filter(e=>e.trim()).slice(-5):[])}}else w&&J(`Docker isn't running, so the database wasn't provisioned. Set POSTGRES_URL in .env, or start Docker and re-run for automatic setup.`);K([`${M(`packages/config/src/site.ts`)} and ${M(`web/next/content`)}`,`to manage branding and blogs & docs respectively`].join(`
37
- `),`Edit and make it yours`),_e(`${b} is ready`);let T=[];y!==process.cwd()&&T.push(M(`cd ${u}`)),X(y)||T.push(`set POSTGRES_URL in .env`),S||T.push(M(`bun run db:migrate`)),T.push(M(`bun run dev`)),K(T.join(`
38
- `),`Next steps`),U(`Learn more ${V(`https://zerostarter.dev/docs`)}`)},rt=`Usage:
35
+ --waitlist, --no-waitlist The /waitlist (off leaves a plain landing home)`,tt=e=>!b(e)||x(e).filter(e=>e!==`.git`).length===0,Q=e=>d(_(e,`packages/config/src/site.ts`)),nt=e=>{let t=e,{root:n}=v(t);for(;;){if(b(_(t,`bun.lock`))||b(_(t,`bun.lockb`)))return t;let e=_(t,`package.json`);if(b(e))try{if(JSON.parse(ee(e,`utf8`)).workspaces)return t}catch{}if(t===n)return null;t=g(t)}},rt=async e=>{let{positionals:t,values:n}=Je(et,{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`},"api-docs":{type:`boolean`},"no-api-docs":{type:`boolean`},blog:{type:`boolean`},"no-blog":{type:`boolean`},docs:{type:`boolean`},"no-docs":{type:`boolean`},"internal-docs":{type:`boolean`},"no-internal-docs":{type:`boolean`},waitlist:{type:`boolean`},"no-waitlist":{type:`boolean`}}});if(n.help){console.log(et);return}n[`dry-run`]||await $e(!!n.yes);let r=z()&&!n.yes,i=n.canary?`canary`:`main`,a=n,o=Z.some(e=>a[e.flag]||a[`no-${e.flag}`]),s={...u};for(let e of Z)s[e.value]=a[`no-${e.flag}`]?!1:a[e.flag]?!0:u[e.value];let c=t[0]??`.`,l=y(c),p=Q(l),h=!p&&!tt(l);if(!p&&!n[`dry-run`]){let e=nt(h?process.cwd():g(l));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(n[`dry-run`]||V(B(`https://zerostarter.dev`)),h){if(!r)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.`);c=e}let v=y(c),b=m(v),ee={name:b},x=`--canary ignored: converting the existing checkout in place, so nothing is fetched.`,te=e=>Z.filter(t=>e[t.value]).map(e=>e.value).join(`, `)||`none`;if(n[`dry-run`]){console.log(`bunx zerostarter init (dry run)`),console.log(` target: ${v}`),console.log(` name: ${b}`),console.log(` mode: ${Q(v)?`in place`:`fetch ${i}`}`),console.log(` features: ${te(s)}`),Q(v)&&n.canary&&console.log(` note: ${x}`);return}if(p&&r&&!await J(`Convert ${b} in place? This rewrites files and commits.`,!1)){U(`Aborted`);return}if(r&&!o){let e=new Set(await Se(`Which optional surfaces should this fork ship with?`,Z.map(e=>({value:e.value,label:e.label,checked:u[e.value]}))));for(let t of Z)s[t.value]=e.has(t.value)}if(Q(v))n.canary&&q(x);else{let e=n.canary?` (canary)`:``;await be(`Fetching the latest ZeroStarter${e}`,`Fetched the latest ZeroStarter${e}`,()=>Re(v,i))}d(_(v,`.git`))||(await Ke(v),await X(v,`ci(init): scaffold from zerostarter`),await qe(v,`main`)),await be(`Rebranding to ${b}`,`Rebranded to ${b}`,()=>f(v,ee,s)),await Fe(v),await X(v,`ci(init): re-baseline as ${b}`),ke(v);let ne=!1,S=await Te(),re=Y(v),C=!1;if(re?n.db&&q(`--db ignored: POSTGRES_URL is already set in .env.`):C=n.db?!0:r?await J(`Provision a local Postgres database?`,S):S,C&&S)try{await Pe(v),ne=!0}catch(e){if(Y(v))q(`Postgres is provisioned, but the migration failed; run bun run db:migrate.`);else{let t=e instanceof Error?e.message.trim():String(e);q(`Database setup failed; set POSTGRES_URL in .env yourself.`,t?t.split(`
36
+ `).filter(e=>e.trim()).slice(-5):[])}}else C&&q(`Docker isn't running, so the database wasn't provisioned. Set POSTGRES_URL in .env, or start Docker and re-run for automatic setup.`);G([`${M(`packages/config/src/site.ts`)} and ${M(`web/next/content`)}`,`to manage branding and blogs & docs respectively`].join(`
37
+ `),`Edit and make it yours`),ye(`${b} is ready`);let w=[];v!==process.cwd()&&w.push(M(`cd ${c}`)),Y(v)||w.push(`set POSTGRES_URL in .env`),ne||w.push(M(`bun run db:migrate`)),w.push(M(`bun run dev`)),G(w.join(`
38
+ `),`Next steps`),H(`Learn more ${B(`https://zerostarter.dev/docs`)}`)},it=`Usage:
39
39
  $ bunx zerostarter reinit [dir] [options]
40
40
 
41
41
  Re-scaffold an existing git repo (default .) as a fresh ZeroStarter: delete every
@@ -45,8 +45,8 @@ branch; push when ready.
45
45
 
46
46
  Options:
47
47
  -y, --yes Skip the confirmation prompt
48
- -h, --help Display help`,it=async t=>{let{positionals:n,values:r}=qe(rt,{allowPositionals:!0,args:t,options:{help:{short:`h`,type:`boolean`},yes:{short:`y`,type:`boolean`}}});if(r.help){console.log(rt);return}await Qe(!!r.yes);let i=v(n[0]??`.`),a=p(i),o=B()&&!r.yes;if(await He(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.`),H(V(`https://zerostarter.dev`)),o&&!await Y(`Delete every file in ${a} (keeping .git and .env*) and re-scaffold?`,!1)){W(`Aborted`);return}await Ue(i,O(`reinit failed; restored your committed files (deleted gitignored files, except .env*, are gone).`),async()=>{e(i),await Le(i),q(`Fetched the latest ZeroStarter (kept .git and .env*)`),d(i,{name:a}),q(`Rebranded to ${a}`),await Ne(i),De(i),await Ke(i,`ci(reinit): re-baseline as ${a}`)});let s=[];X(i)||s.push(`set POSTGRES_URL in .env`),s.push(M(`bun run db:migrate`)),s.push(M(`bun run dev`)),s.push(M(`git push`)),K(s.join(`
49
- `),`Next steps`),U(D(`${a} re-scaffolded; .git history, remote, and .env* files are intact`))},at=`Usage:
48
+ -h, --help Display help`,at=async e=>{let{positionals:t,values:n}=Je(it,{allowPositionals:!0,args:e,options:{help:{short:`h`,type:`boolean`},yes:{short:`y`,type:`boolean`}}});if(n.help){console.log(it);return}await $e(!!n.yes);let r=y(t[0]??`.`),i=m(r),a=z()&&!n.yes;if(await We(r,`No git repository in ${r}. 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.`),V(B(`https://zerostarter.dev`)),a&&!await J(`Delete every file in ${i} (keeping .git and .env*) and re-scaffold?`,!1)){U(`Aborted`);return}await Ge(r,O(`reinit failed; restored your committed files (deleted gitignored files, except .env*, are gone).`),async()=>{c(r),await ze(r),K(`Fetched the latest ZeroStarter (kept .git and .env*)`),f(r,{name:i}),K(`Rebranded to ${i}`),await Fe(r),ke(r),await X(r,`ci(reinit): re-baseline as ${i}`)});let o=[];Y(r)||o.push(`set POSTGRES_URL in .env`),o.push(M(`bun run db:migrate`)),o.push(M(`bun run dev`)),o.push(M(`git push`)),G(o.join(`
49
+ `),`Next steps`),H(D(`${i} re-scaffolded; .git history, remote, and .env* files are intact`))},ot=`Usage:
50
50
  $ bunx zerostarter sync [dir] [options]
51
51
 
52
52
  Re-baseline an existing fork (default .) on the latest ZeroStarter: a gitpick overlay
@@ -55,9 +55,9 @@ identity, and favicon are preserved. Requires a clean tree; lands as a reviewabl
55
55
  you commit yourself.
56
56
 
57
57
  Options:
58
- -h, --help Display help`,ot=async e=>{let{positionals:t,values:n}=qe(at,{allowPositionals:!0,args:e,options:{help:{short:`h`,type:`boolean`}}});if(n.help){console.log(at);return}await Qe();let l=v(t[0]??`.`);await He(l,`No git repository in ${l}. Run sync inside an existing fork.`,`Working tree has uncommitted changes. Commit or stash them first so the sync lands as a reviewable diff.`),H(V(`https://zerostarter.dev`));let d=g(l,`package.json`),p=new Map(u(l).map(e=>[e,a(e)])),m=c(await Re()).preserve;m.length===0&&J(`No PRESERVE_ON_SYNC directive found; fork-owned files may be overwritten.`),await Ue(l,O(`Sync failed; rolled the working tree back to your last commit.`),async()=>{await Le(l),o(l),f(g(l,`.gitpickignore`));for(let[e,t]of p)s(e)&&r(e,i(t,a(e),e===d));await Be(l,m)}),q(`Overlaid the latest ZeroStarter (content, public/marketing, and branding preserved)`),await Ne(l),K([`Starter files were updated (edits overwritten); your content, public/marketing, and branding were preserved.`,O(`Review the diff and commit: git -C ${l} status`)].join(`
59
- `),`Review the changes`),U(M(`Synced to the latest ZeroStarter`))},{author:st,name:$,version:ct}=he,lt=`Version:
60
- ${$}@${ct}
58
+ -h, --help Display help`,st=async r=>{let{positionals:a,values:c}=Je(ot,{allowPositionals:!0,args:r,options:{help:{short:`h`,type:`boolean`}}});if(c.help){console.log(ot);return}await $e();let u=y(a[0]??`.`);await We(u,`No git repository in ${u}. Run sync inside an existing fork.`,`Working tree has uncommitted changes. Commit or stash them first so the sync lands as a reviewable diff.`),V(B(`https://zerostarter.dev`));let f=_(u,`package.json`),m=new Map(t(u).map(e=>[e,p(e)])),h=o(await Be()).preserve;h.length===0&&q(`No PRESERVE_ON_SYNC directive found; fork-owned files may be overwritten.`),await Ge(u,O(`Sync failed; rolled the working tree back to your last commit.`),async()=>{await ze(u),s(u),n(_(u,`.gitpickignore`));for(let[t,n]of m)d(t)&&l(t,e(n,p(t),t===f));i(u),await He(u,h)}),K(`Overlaid the latest ZeroStarter (content, public/marketing, and branding preserved)`),await Fe(u),G([`Starter files were updated (edits overwritten); your content, public/marketing, and branding were preserved.`,O(`Review the diff and commit: git -C ${u} status`)].join(`
59
+ `),`Review the changes`),H(M(`Synced to the latest ZeroStarter`))},{author:ct,name:$,version:lt}=_e,ut=`Version:
60
+ ${$}@${lt}
61
61
 
62
62
  Go from zero to a production-ready SaaS, rebranded and ready to ship.
63
63
 
@@ -75,4 +75,4 @@ Options:
75
75
  -h, --help Display help
76
76
 
77
77
  Author:
78
- ${st.name} <${st.email}> (${ge(st.url)})`;(async()=>{try{let e=process.argv.slice(2),t=e[0],n=e.slice(1);switch(t){case`init`:return await nt(n);case`reinit`:return await it(n);case`sync`:return await ot(n);case void 0:case`-h`:case`--help`:console.log(lt);return;case`-v`:case`--version`:console.log(`${$}@${ct}`);return;default:console.error(j(`Unknown command: ${t}\n`)),console.log(lt),process.exit(1)}}catch(e){pe(e),process.exit(1)}})();export{};
78
+ ${ct.name} <${ct.email}> (${ve(ct.url)})`;(async()=>{try{let e=process.argv.slice(2),t=e[0],n=e.slice(1);switch(t){case`init`:return await rt(n);case`reinit`:return await at(n);case`sync`:return await st(n);case void 0:case`-h`:case`--help`:console.log(ut);return;case`-v`:case`--version`:console.log(`${$}@${lt}`);return;default:console.error(j(`Unknown command: ${t}\n`)),console.log(ut),process.exit(1)}}catch(e){he(e),process.exit(1)}})();export{};
@@ -1,9 +1,9 @@
1
1
  import{dirname as e,join as t}from"node:path";import{existsSync as n,mkdirSync as r,readFileSync as i,readdirSync as a,rmSync as o,writeFileSync as s}from"node:fs";const c=e=>{let t=[],n=[],r=!1;for(let i of e.split(`
2
- `)){let e=i.trim();if(e){if(!r&&e.startsWith(`# PRESERVE_ON_SYNC`)){n=e.slice(18).replace(/^\s*-\s*/,``).split(`,`).map(e=>e.trim()).filter(Boolean),r=!0;continue}e.startsWith(`#`)||t.push(e)}}return{excludes:t,preserve:n}},l=e=>n(e),u=e=>i(e,`utf8`),d=(t,n)=>{r(e(t),{recursive:!0}),s(t,n)},f=e=>{o(e,{force:!0,recursive:!0})},p=new Set([`node_modules`,`.next`,`.turbo`,`dist`]),m=(e,n=!0)=>{for(let r of a(e,{withFileTypes:!0})){let i=t(e,r.name);if(r.name===`.git`){if(n)continue;o(i,{force:!0,recursive:!0});continue}r.isDirectory()?p.has(r.name)?o(i,{force:!0,recursive:!0}):(m(i,!1),a(i).length===0&&o(i,{force:!0,recursive:!0})):r.name.startsWith(`.env`)||o(i,{force:!0})}},h=e=>{let n=[];for(let r of a(e,{withFileTypes:!0})){if(r.name===`.git`||p.has(r.name))continue;let i=t(e,r.name);r.isDirectory()?n.push(...h(i)):r.name===`package.json`&&n.push(i)}return n},g=e=>JSON.parse(u(e)),_=(e,t)=>{d(e,`${JSON.stringify(t,null,2)}\n`)},v=(e,t)=>{if(!n(e))return!1;let r=u(e),i=r.replace(t,``);return i===r?!1:(s(e,i),!0)},y=[`homepage`,`bugs`,`license`,`author`,`repository`,`funding`],b=[`name`,`version`,...y],x=(e,t)=>{let n={...e,...t};return Object.keys(n).length>0?n:void 0},S=(e,t)=>{let n=Array.isArray(e)?e:[],r=Array.isArray(t)?t:[];return n.length||r.length?[...new Set([...r,...n])]:void 0},C=[`dependencies`,`devDependencies`,`optionalDependencies`,`peerDependencies`,`resolutions`,`catalog`,`scripts`,`overrides`],w=(e,t,n)=>{let r={...t};for(let n of Object.keys(e))n in t||(r[n]=e[n]);for(let n of C){let i=x(e[n],t[n]);i&&(r[n]=i)}let i=S(e.workspaces,t.workspaces);if(i&&(r.workspaces=i),n)for(let t of b)t in e?r[t]=e[t]:delete r[t];return r},T=`https://github.com/nrjdalal/zerostarter`,E=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)||`app`,D=(e,t,n)=>e.replaceAll(`ZeroStarter`,n).replaceAll(`zerostarter`,t),O=()=>`> [!CAUTION]
3
- > Synced from ${T}. If you customize this skill or remove this note, it stops syncing and your fork owns it.`,k=(e,n)=>{let r=t(e,`.agents/skills`);if(!l(r))return;let i=E(n.name);for(let e of a(r,{withFileTypes:!0})){if(!e.isDirectory())continue;let a=t(r,e.name,`SKILL.md`);if(!l(a))continue;let o=u(a).split(`
2
+ `)){let e=i.trim();if(e){if(!r&&e.startsWith(`# PRESERVE_ON_SYNC`)){n=e.slice(18).replace(/^\s*-\s*/,``).split(`,`).map(e=>e.trim()).filter(Boolean),r=!0;continue}e.startsWith(`#`)||t.push(e)}}return{excludes:t,preserve:n}},l=e=>n(e),u=e=>i(e,`utf8`),d=(t,n)=>{r(e(t),{recursive:!0}),s(t,n)},f=e=>{o(e,{force:!0,recursive:!0})},p=new Set([`node_modules`,`.next`,`.turbo`,`dist`]),m=(e,n=!0)=>{for(let r of a(e,{withFileTypes:!0})){let i=t(e,r.name);if(r.name===`.git`){if(n)continue;o(i,{force:!0,recursive:!0});continue}r.isDirectory()?p.has(r.name)?o(i,{force:!0,recursive:!0}):(m(i,!1),a(i).length===0&&o(i,{force:!0,recursive:!0})):r.name.startsWith(`.env`)||o(i,{force:!0})}},h=e=>{let n=[];for(let r of a(e,{withFileTypes:!0})){if(r.name===`.git`||p.has(r.name))continue;let i=t(e,r.name);r.isDirectory()?n.push(...h(i)):r.name===`package.json`&&n.push(i)}return n},g=e=>JSON.parse(u(e)),_=(e,t)=>{d(e,`${JSON.stringify(t,null,2)}\n`)},v=(e,t)=>{if(!n(e))return!1;let r=u(e),i=r.replace(t,``);return i===r?!1:(s(e,i),!0)},y=[`homepage`,`bugs`,`license`,`author`,`repository`,`funding`],b=[`name`,`version`,...y],x=(e,t)=>{let n={...e,...t};return Object.keys(n).length>0?n:void 0},S=(e,t)=>{let n=Array.isArray(e)?e:[],r=Array.isArray(t)?t:[];return n.length||r.length?[...new Set([...r,...n])]:void 0},C=[`dependencies`,`devDependencies`,`optionalDependencies`,`peerDependencies`,`resolutions`,`catalog`,`scripts`,`overrides`],w=(e,t,n)=>{let r={...t};for(let n of Object.keys(e))n in t||(r[n]=e[n]);for(let n of C){let i=x(e[n],t[n]);i&&(r[n]=i)}let i=S(e.workspaces,t.workspaces);if(i&&(r.workspaces=i),n)for(let t of b)t in e?r[t]=e[t]:delete r[t];return r},T=`https://github.com/nrjdalal/zerostarter`,E=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)||`app`,D=(e,t,n)=>e.replaceAll(`ZeroStarter`,n).replace(/(?<!bunx )zerostarter(?! scaffolding CLI)/g,t),O=()=>`> [!CAUTION]
3
+ > Synced from ${T}. Customize this skill or remove this note to stop syncing.`,k=(e,n)=>{let r=t(e,`.agents/skills`);if(!l(r))return;let i=E(n.name);for(let e of a(r,{withFileTypes:!0})){if(!e.isDirectory())continue;let a=t(r,e.name,`SKILL.md`);if(!l(a))continue;let o=u(a).split(`
4
4
  `),s=o.indexOf(`---`),c=o.indexOf(`---`,s+1);if(s!==0||c===-1)throw Error(`.agents/skills/${e.name}/SKILL.md has no frontmatter to reconcile (the skill shape drifted). Update packages/cli/src/skills.ts.`);let f=o.slice(s+1,c).map(e=>e.startsWith(`source:`)?`source: ${T}`:D(e,i,n.name));f.some(e=>e.startsWith(`source:`))||f.push(`source: ${T}`);let p=D(o.slice(c+1).join(`
5
5
  `),i,n.name).replace(/^\n+/,``);d(a,`---\n${f.join(`
6
- `)}\n---\n\n${O()}\n\n${p}`)}},A={apiDocs:!0,blog:!0,docs:!0,internalDocs:!0,waitlist:!1},j=e=>`// Optional surfaces a fork enables or disables. Typed boolean (not \`as const\`) so a fork can flip them and the runtime gates are not dead code. Off means the routes 404 and the links, nav, sitemap, llms, and search drop the surface. waitlist off makes the home a plain landing page.
6
+ `)}\n---\n\n${O()}\n\n${p}`)}},A=e=>{let n=g(t(e,`package.json`)).name;n&&k(e,{name:n})},j={apiDocs:!0,blog:!0,docs:!0,internalDocs:!0,waitlist:!1},M=e=>`// Optional surfaces a fork enables or disables. Typed boolean (not \`as const\`) so a fork can flip them and the runtime gates are not dead code. Off means the routes 404 and the links, nav, sitemap, llms, and search drop the surface. waitlist off makes the home a plain landing page.
7
7
  export const features = {
8
8
  apiDocs: ${e.apiDocs},
9
9
  blog: ${e.blog},
@@ -12,7 +12,7 @@ export const features = {
12
12
  waitlist: ${e.waitlist},
13
13
  }
14
14
 
15
- export type Feature = keyof typeof features`,M=({name:e},t=A)=>{let n=e.charAt(0).toUpperCase()+e.slice(1);return`// Brand identity for this app: the single source a fork edits to rebrand. web reads it via lib/config.ts.
15
+ export type Feature = keyof typeof features`,N=({name:e},t=j)=>{let n=e.charAt(0).toUpperCase()+e.slice(1);return`// Brand identity for this app: the single source a fork edits to rebrand. web reads it via lib/config.ts.
16
16
  export const site = {
17
17
  name: "${n}",
18
18
  description: "${n} is just getting started. Tell its story here.",
@@ -34,8 +34,8 @@ export const site = {
34
34
 
35
35
  export type Site = typeof site
36
36
 
37
- ${j(t)}
38
- `},N=()=>`import { features, site } from "@packages/config/site"
37
+ ${M(t)}
38
+ `},P=()=>`import { features, site } from "@packages/config/site"
39
39
  import { redirect } from "next/navigation"
40
40
 
41
41
  // Fresh fork: the waitlist capture when the waitlist feature is on, otherwise a plain landing page. Replace this with your real home when ready.
@@ -51,7 +51,7 @@ export default function Home() {
51
51
  </main>
52
52
  )
53
53
  }
54
- `,P=()=>'# AGENTS.md\n\nGuidance for AI coding agents working in this repository.\n\n## Instructions\n\n- ALWAYS: Use `@/` for imports, and follow the `design` skill for UI and styling conventions.\n- ALWAYS: Keep documentation in sync with every change.\n- NEVER: Include "Co-authored-by" in commit messages.\n- NEVER: Use em-dashes (the long dash, U+2014) in code, comments, docs, or copy. Regular hyphens are fine; for a pause or aside, use a comma, colon, or period.\n\n## Skills\n\nCustom skills live in `.agents/skills` (symlinked to `.claude/skills`). Start with the `codebase-map` skill to orient, then load the task skill that fits (`api-endpoint`, `db-migration`, `dev`, `design`, and more).\n',F=({name:e})=>`# ${e.charAt(0).toUpperCase()+e.slice(1)}
54
+ `,F=()=>'# AGENTS.md\n\nGuidance for AI coding agents working in this repository.\n\n## Instructions\n\n- ALWAYS: Use `@/` for imports, and follow the `design` skill for UI and styling conventions.\n- ALWAYS: Keep documentation in sync with every change.\n- NEVER: Include "Co-authored-by" in commit messages.\n- NEVER: Use em-dashes (the long dash, U+2014) in code, comments, docs, or copy. Regular hyphens are fine; for a pause or aside, use a comma, colon, or period.\n\n## Skills\n\nCustom skills live in `.agents/skills` (symlinked to `.claude/skills`). Start with the `codebase-map` skill to orient, then load the task skill that fits (`api-endpoint`, `db-migration`, `dev`, `design`, and more).\n',I=({name:e})=>`# ${e.charAt(0).toUpperCase()+e.slice(1)}
55
55
 
56
56
  Built on top of [ZeroStarter](https://zerostarter.dev).
57
57
 
@@ -62,7 +62,7 @@ bun run dev
62
62
  \`\`\`
63
63
 
64
64
  This serves named \`.localhost\` dev URLs via portless (\`bunx portless list\` shows them); \`PORTLESS=0 bun run dev\` uses fixed ports instead (web \`:3000\`, api \`:4000\`).
65
- `,I=()=>`---
65
+ `,L=()=>`---
66
66
  slug: /docs
67
67
  title: Introduction
68
68
  description: Documentation.
@@ -71,7 +71,7 @@ description: Documentation.
71
71
  # Introduction
72
72
 
73
73
  This is your documentation home. Start writing, this page is yours.
74
- `,L=()=>`---
74
+ `,R=()=>`---
75
75
  slug: /console/docs
76
76
  title: Introduction
77
77
  description: Internal documentation.
@@ -80,7 +80,7 @@ description: Internal documentation.
80
80
  # Introduction
81
81
 
82
82
  Your team's internal docs live here.
83
- `,R=e=>`---
83
+ `,z=e=>`---
84
84
  title: Blog
85
85
  description: Latest articles and updates
86
86
  createdAt: ${e}
@@ -89,7 +89,7 @@ createdAt: ${e}
89
89
  ## Recent Posts
90
90
 
91
91
  <BlogPostList />
92
- `,z=e=>`---
92
+ `,B=e=>`---
93
93
  title: Hello World
94
94
  description: The first post on your new blog.
95
95
  createdAt: ${e}
@@ -99,7 +99,7 @@ publishedAt: ${e}
99
99
  ## Hello World
100
100
 
101
101
  Your very first post. Replace it with something worth reading.
102
- `,B=()=>`import type { DocsConfig } from "./src/lib/docs"
102
+ `,V=()=>`import type { DocsConfig } from "./src/lib/docs"
103
103
 
104
104
  const docsConfig = {
105
105
  docs: {
@@ -125,4 +125,4 @@ const docsConfig = {
125
125
  } satisfies DocsConfig
126
126
 
127
127
  export default docsConfig
128
- `,V=(e,...n)=>t(e,...n),H=e=>{let t=V(e,`.gitpickignore`);if(l(t)){for(let n of c(u(t)).excludes){if(/[*?![\]]/.test(n))throw Error(`.gitpickignore entry "${n}" is not a literal path; the in-place converter only supports literal paths (a glob or negation would diverge from gitpick's fetch).`);f(V(e,n))}f(t)}},U=/[ \t]*\{[^}\r\n]*href:[ \t]*["']\/hire["'][^}\r\n]*\},?[ \t]*\r?\n/,W=(e,t)=>{let n=new Date,r=n.toISOString().slice(0,10),i=[n.getFullYear(),n.getMonth()+1,n.getDate()].map(e=>String(e).padStart(2,`0`)).join(`-`),a=i<r?i:r;d(V(e,`web/next/content/docs/index.mdx`),I()),d(V(e,`web/next/content/blog/index.mdx`),R(a)),d(V(e,`web/next/content/blog/hello-world.mdx`),z(a)),d(V(e,`web/next/content/console/docs/index.mdx`),L()),d(V(e,`web/next/docs.config.ts`),B()),d(V(e,`web/next/public/.gitkeep`),``),d(V(e,`web/next/src/app/page.tsx`),N()),d(V(e,`AGENTS.md`),P()),d(V(e,`README.md`),F(t))},G=e=>{let t=V(e,`web/next/src/lib/fonts.ts`),n=V(e,`web/next/src/lib/marketing/fonts.ts`),r=V(e,`web/next/src/components/common/navbar.tsx`);if(v(r,U),l(n))throw Error(`web/next/src/lib/marketing/fonts.ts survived the fork strip (add web/next/src/lib/marketing/ to .gitpickignore).`);if(l(t)&&u(t).includes(`fonts/marketing/`))throw Error(`fonts.ts references fonts/marketing/; author-only marketing fonts must live in the fork-excluded web/next/src/lib/marketing/, not the shared fonts.ts.`);if(l(r)&&/href:\s*["']\/hire["']/.test(u(r)))throw Error(`common/navbar.tsx still has the /hire entry after fixDangling (regex drift). Update packages/cli/src/convert.ts.`)},K=(e,t,n)=>{d(V(e,`packages/config/src/site.ts`),M(t,n));let r=E(t.name),i=V(e,`package.json`),a=g(i);a.name=r,a.version=`0.0.0`;for(let e of y)delete a[e];_(i,a);for(let[t,n]of[[`web/next`,r],[`api/hono`,`api.${r}`]]){let r=V(e,t,`package.json`),i=g(r),a=i.portless;if(!a||typeof a!=`object`||Array.isArray(a))throw Error(`${t}/package.json has no "portless" object to rebrand (the dev-URL setup drifted). Update packages/cli/src/convert.ts.`);let o=a;o.name=n,_(r,i)}},q=(e,t,n=A)=>{H(e),W(e,t),G(e),K(e,t,n),k(e,t)};export{m as a,u as c,d,_ as f,w as i,g as l,G as n,l as o,c as p,A as r,h as s,q as t,f as u};
128
+ `,H=(e,...n)=>t(e,...n),U=e=>{let t=H(e,`.gitpickignore`);if(l(t)){for(let n of c(u(t)).excludes){if(/[*?![\]]/.test(n))throw Error(`.gitpickignore entry "${n}" is not a literal path; the in-place converter only supports literal paths (a glob or negation would diverge from gitpick's fetch).`);f(H(e,n))}f(t)}},W=/[ \t]*\{[^}\r\n]*href:[ \t]*["']\/hire["'][^}\r\n]*\},?[ \t]*\r?\n/,G=(e,t)=>{let n=new Date,r=n.toISOString().slice(0,10),i=[n.getFullYear(),n.getMonth()+1,n.getDate()].map(e=>String(e).padStart(2,`0`)).join(`-`),a=i<r?i:r;d(H(e,`web/next/content/docs/index.mdx`),L()),d(H(e,`web/next/content/blog/index.mdx`),z(a)),d(H(e,`web/next/content/blog/hello-world.mdx`),B(a)),d(H(e,`web/next/content/console/docs/index.mdx`),R()),d(H(e,`web/next/docs.config.ts`),V()),d(H(e,`web/next/public/.gitkeep`),``),d(H(e,`web/next/src/app/page.tsx`),P()),d(H(e,`AGENTS.md`),F()),d(H(e,`README.md`),I(t))},K=e=>{let t=H(e,`web/next/src/lib/fonts.ts`),n=H(e,`web/next/src/lib/marketing/fonts.ts`),r=H(e,`web/next/src/components/common/navbar.tsx`);if(v(r,W),l(n))throw Error(`web/next/src/lib/marketing/fonts.ts survived the fork strip (add web/next/src/lib/marketing/ to .gitpickignore).`);if(l(t)&&u(t).includes(`fonts/marketing/`))throw Error(`fonts.ts references fonts/marketing/; author-only marketing fonts must live in the fork-excluded web/next/src/lib/marketing/, not the shared fonts.ts.`);if(l(r)&&/href:\s*["']\/hire["']/.test(u(r)))throw Error(`common/navbar.tsx still has the /hire entry after fixDangling (regex drift). Update packages/cli/src/convert.ts.`)},q=(e,t,n)=>{d(H(e,`packages/config/src/site.ts`),N(t,n));let r=E(t.name),i=H(e,`package.json`),a=g(i);a.name=r,a.version=`0.0.0`;for(let e of y)delete a[e];_(i,a);for(let[t,n]of[[`web/next`,r],[`api/hono`,`api.${r}`]]){let r=H(e,t,`package.json`),i=g(r),a=i.portless;if(!a||typeof a!=`object`||Array.isArray(a))throw Error(`${t}/package.json has no "portless" object to rebrand (the dev-URL setup drifted). Update packages/cli/src/convert.ts.`);let o=a;o.name=n,_(r,i)}},J=(e,t,n=j)=>{U(e),G(e,t),K(e),q(e,t,n),k(e,t)};export{w as a,h as c,f as d,d as f,A as i,u as l,c as m,K as n,m as o,_ as p,j as r,l as s,J as t,g as u};
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./convert-qIUh5kib.mjs";export{e as convertRepo};
1
+ import{t as e}from"./convert-Crk8STXb.mjs";export{e as convertRepo};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zerostarter",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Go from zero to a production-ready SaaS, rebranded and ready to ship.",
5
5
  "keywords": [
6
6
  "cli",