generatesaas 1.23.0 → 1.23.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/index.js +3 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -339,6 +339,7 @@ export * from "./billing-fields";
|
|
|
339
339
|
export * from "./social-providers";
|
|
340
340
|
export * from "./blog";
|
|
341
341
|
export * from "./cache";
|
|
342
|
+
export * from "./companion";
|
|
342
343
|
export * from "./footer";
|
|
343
344
|
export * from "./i18n";
|
|
344
345
|
export * from "./landing";
|
|
@@ -1412,7 +1413,7 @@ export { ops } from "./${n}/index";
|
|
|
1412
1413
|
${f}`:a.message))}else i()})})}async function wi(e){if(!De("pnpm"))return U.log.warn("pnpm not found. Skipping lockfile regeneration."),!1;try{return await Ce("pnpm",["install","--lockfile-only","--no-frozen-lockfile","--config.minimumReleaseAge=0"],e),!0}catch(t){let n=t instanceof Error?t.message:String(t);return U.log.warn(`Lockfile regeneration failed: ${n}`),U.log.warn("Deploys using --frozen-lockfile may fail."),!1}}async function Si(e){if(!De("pnpm"))return U.log.warn("pnpm not found. Skipping dependency installation."),U.log.info("Install pnpm: https://pnpm.io/installation"),!1;let t=U.spinner();t.start("Installing dependencies (this may take a minute)...");try{return await Ce("pnpm",["install","--config.minimumReleaseAge=0"],e),t.stop("Dependencies installed."),!0}catch(n){t.stop("Dependency installation failed.");let r=n instanceof Error?n.message:String(n);return U.log.warn(`pnpm install failed: ${r}`),U.log.warn("You can run it manually later."),!1}}async function Ei(e){if(!De("pnpm"))return!1;let t=U.spinner();t.start("Generating baseline database migration...");try{return await Ce("pnpm",["-F","@repo/database","generate"],e),t.stop("Baseline migration generated."),!0}catch(n){t.stop("Baseline migration generation failed.");let r=n instanceof Error?n.message:String(n);return U.log.warn(`Could not generate baseline migration: ${r}`),U.log.warn("Run 'pnpm -F @repo/database generate' before your first deploy."),!1}}async function Ai(e){try{return await ki(Pn(e,".git")),U.log.info("Git repository already exists, skipping init."),!0}catch{}if(!De("git"))return U.log.warn("git not found. Skipping repository initialization."),!1;let t=U.spinner();t.start("Initializing git repository...");try{return await Ce("git",["init"],e),await Ce("git",["add","-A"],e),await Ce("git",["commit","--no-verify","-m","Initial commit from GenerateSaaS"],e),t.stop("Git repository initialized."),!0}catch{return t.stop("Git initialization failed."),U.log.warn("You can run git init manually later."),!1}}async function Ii(e){if(!De("pnpm"))return!1;try{await ki(Pn(e,".git"))}catch{return!1}try{let t=JSON.parse(await hs(Pn(e,"package.json"),"utf-8")),n=!!t.devDependencies?.["simple-git-hooks"],r=!!t["simple-git-hooks"];if(!n||!r)return!1}catch{return!1}try{return await Ce("pnpm",["exec","simple-git-hooks"],e),!0}catch{return U.log.warn("Could not install git hooks. Run 'pnpm exec simple-git-hooks' manually."),!1}}import*as Qe from"@clack/prompts";import X from"picocolors";function Pi(e,t){t.dockerComposeGenerated&&!t.dockerAvailable&&Qe.log.warn("Docker not found. Install Docker to run local services: https://docs.docker.com/get-docker/");let n=[];if(n.push(`cd ${e.projectDir}`),t.pnpmInstalled||n.push("pnpm install"),t.dockerComposeGenerated){let o=e.dockerServices.map(a=>$e[a].label).join(", ");n.push(`pnpm infra ${X.dim(`# ${o}`)}`)}if(n.push(`pnpm dev ${X.dim("# http://localhost:3000")}`),t.skippedCredentials.length>0&&(n.push(""),n.push(X.dim("Fill in remaining TODO values in .env"))),Qe.note(n.join(`
|
|
1413
1414
|
`),X.yellow("Start Development")),t.dockerComposeGenerated){let o=[];o.push(`App ${X.cyan("http://localhost:3000")}`),e.architecture==="separate"&&o.push(`API ${X.cyan("http://localhost:3010")}`),e.dockerServices.includes("mailpit")&&o.push(`Mailpit ${X.cyan("http://localhost:8025")}`),e.dockerServices.includes("inngest")&&o.push(`Inngest ${X.cyan("http://localhost:8288")}`),Qe.note(o.join(`
|
|
1414
1415
|
`),X.yellow("Dev Tools"))}let r=[],i=ys(e);i.length>0&&r.push(`Set in production: ${X.dim(i.join(", "))}`),r.push("pnpm db:setup # Apply the database schema"),r.push(vs(e)),Qe.note(r.join(`
|
|
1415
|
-
`),X.yellow("Deployment"))}function ys(e){let t=["DATABASE_URL","BETTER_AUTH_SECRET"];return e.cacheProvider==="upstash"?t.push("UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN"):t.push("REDIS_URL"),e.paymentProvider==="stripe"?t.push("STRIPE_SECRET_KEY","STRIPE_WEBHOOK_SECRET"):e.paymentProvider==="polar"&&t.push("POLAR_ACCESS_TOKEN","POLAR_WEBHOOK_SECRET"),e.emailProvider==="ses"?t.push("AMAZON_SES_REGION","AMAZON_SES_KEY","AMAZON_SES_SECRET"):e.emailProvider==="resend"?t.push("RESEND_API_KEY"):t.push("SMTP_HOST","SMTP_PORT"),t}function vs(e){switch(e.deploymentTarget){case"node":return"Deploy with Docker or your preferred Node.js host";case"vercel":return"vercel deploy # Deploy to Vercel"}}import As from"picocolors";var Is="a10a6fb9d7cadde32e37dad52059d17b5d2b916b08c76d8fbcc99982e9a3d87f";async function Ps(e){let t=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(`generatesaas-demo:${e}`)),n=[...new Uint8Array(t).subarray(0,16)].map(r=>r.toString(16).padStart(2,"0")).join("");return`${n.slice(0,8)}-${n.slice(8,12)}-${n.slice(12,16)}-${n.slice(16,20)}-${n.slice(20,32)}`}function Ts(e){if(e===void 0)return;let t=e.trim().replace(/^v/,"");if(!/^\d+\.\d+\.\d+$/.test(t))throw new Error(`Invalid template version "${e}". Use semver like 1.2.3.`);return t}function Ti(e){e.command("init").description("Scaffold a new GenerateSaaS project").argument("[apiKey]","license key (same as --api-key)").option("-n, --name <name>","project name (lowercase, hyphens, starts with letter)").option("--app-name <name>","display name for the app").option("-l, --location <path>","project directory (default: ./{name})").addOption(new Z("--frontend <type>","frontend framework").choices([...Ae])).addOption(new Z("--architecture <type>","fullstack or separate").choices([...je])).addOption(new Z("--payment <provider>","payment provider").choices([...Ue])).addOption(new Z("--email <provider>","email provider").choices([...Me])).option("--org","enable multi-tenancy (organizations)").option("--no-org","disable multi-tenancy").addOption(new Z("--billing-scope <scope>","billing scope (requires --org)").choices([...Fe])).option("--blog","enable blog").option("--no-blog","disable blog").option("--docs","include the docs app (apps/docs, Fumadocs)").option("--no-docs","exclude the docs app").option("--desktop","include the desktop app (apps/tauri, built with Tauri)").option("--no-desktop","exclude the desktop app").option("--desktop-auto","auto-trigger the desktop release workflow on CI success (default: manual-only)").option("--no-desktop-auto","manual-only desktop releases (workflow_dispatch)").option("--desktop-ai","include the desktop AI orchestration layer (requires --desktop)").option("--no-desktop-ai","exclude the desktop AI orchestration layer").option("--ai","include the AI features (chat, models, schedules, integrations); unlocks the companion + MCP server").option("--no-ai","exclude the AI features").option("--rag","include the server-side knowledge base (keyword search over your knowledge/ docs)").option("--no-rag","exclude the server-side knowledge base").option("--companion","include the backend companion feature (pairing, HTTP transport, Companions UI) for the universal OpenCompanion daemon your users install").option("--no-companion","exclude the backend companion feature").option("--mcp-server","include the outward MCP server (the /mcp route + Better Auth mcp() provider)").option("--no-mcp-server","exclude the outward MCP server").option("--ai-byok","AI BYOK mode: end-users bring their own provider key (default)").option("--no-ai-byok","operator-keyed, credit-metered AI platform mode").option("--revenue-sharing","enable revenue sharing").option("--no-revenue-sharing","disable revenue sharing").option("--credits","enable credits system").option("--no-credits","disable credits system (subscription-only)").option("--docker <services>","comma-separated: postgres,redis,inngest,mailpit").option("--ai-tools <tools>","comma-separated: claude-code,cursor,codex,gemini-cli,windsurf").option("--social-providers <providers>","comma-separated: google,github,facebook,discord,x").addOption(new Z("--currency <code>","default currency for billing").choices([...ce])).addOption(new Z("--deploy <target>","deployment target").choices([...le])).addOption(new Z("--database <provider>","database provider").choices([...pe])).addOption(new Z("--cache <provider>","cache provider").choices([...de])).option("--template-version <version>","specific template version to scaffold").option("--api-key <key>","API key (skips interactive prompt)").option("--base-url <url>","public base URL (e.g. https://example.com) - bakes into canonical/og/sitemap").option("-y, --yes","accept defaults for unspecified options (non-interactive)").addOption(new Z("--demo","first-party demo build: keep sample content, mark site non-indexable - requires CI API key").hideHelp()).addOption(new Z("--no-db-migration","skip generating the baseline DB migration (internal: demos/CI/playground)").hideHelp()).action(async(t,n)=>{await Rs(t?{...n,apiKey:t}:n)})}async function Rs(e){let t=performance.now();Un("1.23.
|
|
1416
|
+
`),X.yellow("Deployment"))}function ys(e){let t=["DATABASE_URL","BETTER_AUTH_SECRET"];return e.cacheProvider==="upstash"?t.push("UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN"):t.push("REDIS_URL"),e.paymentProvider==="stripe"?t.push("STRIPE_SECRET_KEY","STRIPE_WEBHOOK_SECRET"):e.paymentProvider==="polar"&&t.push("POLAR_ACCESS_TOKEN","POLAR_WEBHOOK_SECRET"),e.emailProvider==="ses"?t.push("AMAZON_SES_REGION","AMAZON_SES_KEY","AMAZON_SES_SECRET"):e.emailProvider==="resend"?t.push("RESEND_API_KEY"):t.push("SMTP_HOST","SMTP_PORT"),t}function vs(e){switch(e.deploymentTarget){case"node":return"Deploy with Docker or your preferred Node.js host";case"vercel":return"vercel deploy # Deploy to Vercel"}}import As from"picocolors";var Is="a10a6fb9d7cadde32e37dad52059d17b5d2b916b08c76d8fbcc99982e9a3d87f";async function Ps(e){let t=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(`generatesaas-demo:${e}`)),n=[...new Uint8Array(t).subarray(0,16)].map(r=>r.toString(16).padStart(2,"0")).join("");return`${n.slice(0,8)}-${n.slice(8,12)}-${n.slice(12,16)}-${n.slice(16,20)}-${n.slice(20,32)}`}function Ts(e){if(e===void 0)return;let t=e.trim().replace(/^v/,"");if(!/^\d+\.\d+\.\d+$/.test(t))throw new Error(`Invalid template version "${e}". Use semver like 1.2.3.`);return t}function Ti(e){e.command("init").description("Scaffold a new GenerateSaaS project").argument("[apiKey]","license key (same as --api-key)").option("-n, --name <name>","project name (lowercase, hyphens, starts with letter)").option("--app-name <name>","display name for the app").option("-l, --location <path>","project directory (default: ./{name})").addOption(new Z("--frontend <type>","frontend framework").choices([...Ae])).addOption(new Z("--architecture <type>","fullstack or separate").choices([...je])).addOption(new Z("--payment <provider>","payment provider").choices([...Ue])).addOption(new Z("--email <provider>","email provider").choices([...Me])).option("--org","enable multi-tenancy (organizations)").option("--no-org","disable multi-tenancy").addOption(new Z("--billing-scope <scope>","billing scope (requires --org)").choices([...Fe])).option("--blog","enable blog").option("--no-blog","disable blog").option("--docs","include the docs app (apps/docs, Fumadocs)").option("--no-docs","exclude the docs app").option("--desktop","include the desktop app (apps/tauri, built with Tauri)").option("--no-desktop","exclude the desktop app").option("--desktop-auto","auto-trigger the desktop release workflow on CI success (default: manual-only)").option("--no-desktop-auto","manual-only desktop releases (workflow_dispatch)").option("--desktop-ai","include the desktop AI orchestration layer (requires --desktop)").option("--no-desktop-ai","exclude the desktop AI orchestration layer").option("--ai","include the AI features (chat, models, schedules, integrations); unlocks the companion + MCP server").option("--no-ai","exclude the AI features").option("--rag","include the server-side knowledge base (keyword search over your knowledge/ docs)").option("--no-rag","exclude the server-side knowledge base").option("--companion","include the backend companion feature (pairing, HTTP transport, Companions UI) for the universal OpenCompanion daemon your users install").option("--no-companion","exclude the backend companion feature").option("--mcp-server","include the outward MCP server (the /mcp route + Better Auth mcp() provider)").option("--no-mcp-server","exclude the outward MCP server").option("--ai-byok","AI BYOK mode: end-users bring their own provider key (default)").option("--no-ai-byok","operator-keyed, credit-metered AI platform mode").option("--revenue-sharing","enable revenue sharing").option("--no-revenue-sharing","disable revenue sharing").option("--credits","enable credits system").option("--no-credits","disable credits system (subscription-only)").option("--docker <services>","comma-separated: postgres,redis,inngest,mailpit").option("--ai-tools <tools>","comma-separated: claude-code,cursor,codex,gemini-cli,windsurf").option("--social-providers <providers>","comma-separated: google,github,facebook,discord,x").addOption(new Z("--currency <code>","default currency for billing").choices([...ce])).addOption(new Z("--deploy <target>","deployment target").choices([...le])).addOption(new Z("--database <provider>","database provider").choices([...pe])).addOption(new Z("--cache <provider>","cache provider").choices([...de])).option("--template-version <version>","specific template version to scaffold").option("--api-key <key>","API key (skips interactive prompt)").option("--base-url <url>","public base URL (e.g. https://example.com) - bakes into canonical/og/sitemap").option("-y, --yes","accept defaults for unspecified options (non-interactive)").addOption(new Z("--demo","first-party demo build: keep sample content, mark site non-indexable - requires CI API key").hideHelp()).addOption(new Z("--no-db-migration","skip generating the baseline DB migration (internal: demos/CI/playground)").hideHelp()).action(async(t,n)=>{await Rs(t?{...n,apiKey:t}:n)})}async function Rs(e){let t=performance.now();Un("1.23.1");let n,r;try{n=zn(e),r=Ts(e.templateVersion)}catch(v){I.cancel(N(v)),process.exit(1)}let i=I.spinner(),o;try{o=await He({apiKey:e.apiKey,prompt:!e.yes})}catch(v){I.cancel(N(v)),process.exit(1)}e.demo&&wn(o)!==Is&&(I.cancel("--demo is restricted to first-party demo deployments."),process.exit(1));let a=fe(o),s=async()=>{let v=await ve(a),P=v.latest,O=r??P;if(r&&!v.versions.some(Y=>Y.version===O))throw new Error(`Template version "${r}" is not available.`);return{latestVersion:P,selectedVersion:O,desktopAllowed:v.entitlements?.desktopAllowed??!0}};i.start("Verifying access...");let d,m,p=!0;try{({latestVersion:d,selectedVersion:m,desktopAllowed:p}=await s()),i.stop("Access verified."),Te(o)}catch(v){if(i.stop("Access verification failed."),v instanceof M&&v.status===401){e.yes&&(I.cancel("Invalid API key. Cannot prompt in non-interactive mode."),process.exit(1)),I.log.warning("Invalid API key."),o=await lt(),a=fe(o),i.start("Verifying access...");try{({latestVersion:d,selectedVersion:m,desktopAllowed:p}=await s()),i.stop("Access verified."),Te(o)}catch(P){i.stop("Access verification failed."),I.cancel(P instanceof M&&P.status===401?"Invalid API key.":N(P)),process.exit(1)}}else I.cancel(N(v)),process.exit(1)}I.log.success(`Latest version: ${d}`),m!==d&&I.log.success(`Using template version: ${m}`),n.desktop===!0&&!p&&(I.cancel("The desktop app is available on the Pro plan and up. Upgrade your plan at generatesaas.com."),process.exit(1));let f;e.yes?f=Yn(p?n:{...n,desktop:!1}):f=await Jn(n,{desktopAllowed:p});let S;i.start("Activating license...");try{let v=e.demo&&f.baseUrl?await Ps(f.baseUrl):crypto.randomUUID(),P=()=>({frontend:f.frontend,version:m,installId:v,projectName:f.projectName,options:Qn(f)}),O;try{O=await Qt(a,P())}catch(Y){let T=Tt(Y);if(!T?.lastAllowedVersion)throw Y;i.stop("License activation failed."),e.yes&&(I.cancel(`${T.message} Re-run with --template-version ${T.lastAllowedVersion}.`),process.exit(1));let w=await I.confirm({message:`Your update window has ended. Continue with v${T.lastAllowedVersion} (the last version your license covers)?`});(I.isCancel(w)||!w)&&(I.cancel("Setup cancelled."),process.exit(0)),m=T.lastAllowedVersion,i.start(`Activating license for v${m}...`),O=await Qt(a,P())}S={token:O.token,keyHash:wn(o),installId:O.installId??v},i.stop("License activated.")}catch(v){i.stop("License activation failed."),I.cancel(N(v)),process.exit(1)}let b=Es(f.projectDir);if(bs(b)&&ks(b).length>0)if(e.yes)I.log.info(`Directory ${b} is not empty. Merging (keeping existing files, overwriting conflicts).`);else{let P=await I.select({message:`Directory ${b} is not empty.`,options:[{value:"merge",label:"Merge",hint:"keep existing files, overwrite conflicts"},{value:"overwrite",label:"Overwrite",hint:"delete everything and start fresh"},{value:"cancel",label:"Cancel"}]});(I.isCancel(P)||P==="cancel")&&(I.cancel("Setup cancelled."),process.exit(0)),P==="overwrite"&&ws(b,{recursive:!0,force:!0})}let A={...f,projectDir:b,version:m,...e.demo?{docs:!1}:{}};i.start("Downloading template...");try{await Rt(a,m,b),i.stop("Template downloaded.")}catch(v){i.stop("Download failed."),I.cancel(N(v)),process.exit(1)}let W;i.start("Generating project files...");try{if({dockerComposeGenerated:W}=await Bt(A),!e.demo){let v=await xe(b);await l(Ss(b,It),JSON.stringify(v,null," ")+`
|
|
1416
1417
|
`),await hi(b,b)}await bi(b,A.aiTools),await fi(A,S),i.stop("Project files generated.")}catch(v){i.stop("Generation failed."),I.cancel(N(v)),process.exit(1)}await wi(b);let V=await Si(b);V&&A.demo!==!0&&e.dbMigration!==!1&&await Ei(b),await Ai(b),V&&await Ii(b);let R=De("docker"),B=Xt(A).map(v=>v.key).filter(v=>!A.credentials?.[v]);Pi(A,{pnpmInstalled:V,dockerComposeGenerated:W,dockerAvailable:R,skippedCredentials:B}),Mn(),I.log.info(As.dim(`Done in ${((performance.now()-t)/1e3).toFixed(1)}s`))}import{existsSync as Ci}from"fs";import{readFile as Rn}from"fs/promises";import{join as gt,resolve as $s}from"path";import*as D from"@clack/prompts";import et from"picocolors";import{mkdtemp as _s,rm as Os}from"fs/promises";import{tmpdir as xs}from"os";import{join as Cs}from"path";async function Tn(e,t,n,r){let i=await _s(Cs(xs(),"generatesaas-stage-"));try{await Rt(e,t,i),await Bt({...n,projectDir:i}),await Sn(i,r)}finally{await Os(i,{recursive:!0,force:!0})}}function Ri(e){let n=(e.startsWith("v")?e.slice(1):e).match(/^(\d+)\.(\d+)\.(\d+)$/);return n?[Number(n[1]),Number(n[2]),Number(n[3])]:null}function Kt(e,t){let n=Ri(e),r=Ri(t);if(!n||!r)return 0;for(let i=0;i<3;i++)if(n[i]!==r[i])return n[i]-r[i];return 0}import{readFile as Ds}from"fs/promises";import{join as _i}from"path";var Ns=_i(z,"companion-release.json"),Ls=["apps/companion/","packages/companion-protocol/","packages/agent-core-types/","packages/agent-core/","scripts/companion-export/"];async function Oi(e){let t;try{t=await Ds(_i(e,Ns),"utf-8")}catch(r){if(typeof r=="object"&&r!==null&&"code"in r&&r.code==="ENOENT")return null;throw r}let n=JSON.parse(t);return typeof n=="object"&&n!==null&&"version"in n&&typeof n.version=="string"&&n.version.length>0?{version:n.version}:null}function xi(e){return e.some(t=>Ls.some(n=>t.startsWith(n)))}function Di(e){e.command("update").description("Update AI skill files and stage template updates").argument("[mode]","pass 'auto' to mark the staged update for unattended apply by your AI assistant").option("--cwd <path>","project directory (default: current directory)").action(async(t,n)=>{let r=t==="auto"?"auto":void 0,i=$s(n.cwd??process.cwd()),o=gt(i,ge),a;try{a=JSON.parse(await Rn(o,"utf-8"))}catch{D.cancel(".generatesaas/manifest.json not found. Run this from a GenerateSaaS project."),process.exit(1)}let s;try{s=await He()}catch(p){D.cancel(N(p)),process.exit(1)}let d=fe(s),m=D.spinner();try{m.start("Verifying access...");let p;try{p=await ve(d)}catch(w){throw w instanceof M&&w.status===401?new Error("Your saved API key was rejected. Run `generatesaas auth` to update it, or set GENERATESAAS_API_KEY."):w}m.stop("Access verified."),Te(s),m.start("Fetching latest skill files...");let f=await Zn(d,p.latest);await In(i,f.skillMd,f.scripts,a.aiTools);let S=An(a.aiTools);if(m.stop("Skills updated."),D.log.success(`Skill files installed to ${et.cyan(S.length.toString())} locations.`),a.version===p.latest){D.log.info(`Already on the latest version (${a.version}).`);return}let b=JSON.stringify(a);Hn(a);let A=Fn(a),W=Kn(a),V=JSON.stringify(W)!==b;if(a=W,a.licenseToken)try{let w=await er(d,{currentToken:a.licenseToken,newVersion:p.latest});a.licenseToken=w.token,w.licenseKeyHash&&(a.licenseKeyHash=w.licenseKeyHash),await l(o,JSON.stringify(a,null," ")+`
|
|
1417
1418
|
`),V=!1,D.log.success("License refreshed.")}catch(w){let ne=Tt(w);ne&&(D.cancel(ne.message),process.exit(1)),D.log.warn("License refresh skipped.")}V&&await l(o,JSON.stringify(a,null," ")+`
|
|
1418
1419
|
`);let R=mi(a,i),te=gt(i,Wn);m.start(`Staging v${p.latest} (shaped for your config)...`),await Tn(d,p.latest,R,te),m.stop("Template staged.");let{text:B,title:v}=await js(d,p,a.version);B&&D.note(B,v);let P=gt(i,It),O=gt(i,Pt),Y=!Ci(O),T=!Ci(P);if(Y){if(m.start("Building baseline template (one-time migration)..."),await Tn(d,a.version,R,O),T){let w=await xe(O);await l(P,JSON.stringify(w,null," ")+`
|
|
@@ -1431,7 +1432,7 @@ ${s??"_No changelog available for this release._"}`)}return{text:o.join(`
|
|
|
1431
1432
|
`,` .route("/license", licenseRoutes)
|
|
1432
1433
|
`]}];function tc(e){return(e&&e.length>0?e.map(n=>ft[n]):Object.values(ft)).map(n=>Ne(n,En))}function On(e){return Gt(e)?(Zs(e,{recursive:!0}),!0):!1}function nc(e,t){if(!Gt(e))return!1;let n=xn(e,"utf-8"),r=n;for(let i of t)r=r.replace(i,"");return r===n?!1:(Bi(e,r,"utf-8"),!0)}function rc(e){let t=Ne(e,".gitignore");if(!Gt(t))return!1;let n=xn(t,"utf-8"),r=n.split(`
|
|
1433
1434
|
`).filter(i=>!i.includes(".generatesaas")).join(`
|
|
1434
|
-
`);return r===n?!1:(Bi(t,r,"utf-8"),!0)}function Fi(e){e.command("eject").description("Remove all GenerateSaaS ties - manifest, license, heartbeat, skills").action(async()=>{let t=process.cwd(),n=Ne(t,ge),r;try{r=JSON.parse(xn(n,"utf-8"))}catch{K.cancel("No GenerateSaaS project found in this directory."),process.exit(1)}let i=await K.text({message:'Type "eject" to confirm (this cannot be undone):',validate:s=>{if(s!=="eject")return'Type "eject" to confirm, or press Ctrl+C to cancel.'}});if(K.isCancel(i)&&(K.cancel("Eject cancelled."),process.exit(0)),r.licenseToken)try{await fetch("https://generatesaas.com/api/v1/heartbeat",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r.licenseToken}`},body:JSON.stringify({event:"eject",version:r.version,frontend:r.frontend}),signal:AbortSignal.timeout(5e3)}),K.log.info("Recorded the opt-out with generatesaas.com (final event - nothing is sent after this).")}catch{K.log.warn("Could not reach generatesaas.com to record the opt-out. Ejecting anyway.")}let o=[],a=[];for(let s of tc(r.aiTools))On(Ne(t,s))&&o.push(s);for(let s of Qs)On(Ne(t,s))&&o.push(s);On(Ne(t,z))&&o.push(z+"/");for(let s of ec){let d=Ne(t,s.file);nc(d,s.removals)?a.push(s.file):Gt(d)&&K.log.warn(`Could not auto-modify ${s.file} - manually remove license/heartbeat references.`)}rc(t)&&a.push(".gitignore");for(let s of o)K.log.info(`Deleted ${s}`);for(let s of a)K.log.info(`Modified ${s}`);K.log.success("Ejected successfully. This project is now fully standalone.")})}var Le=new ic().name("generatesaas").description("CLI for scaffolding and managing GenerateSaaS projects").version("1.23.
|
|
1435
|
+
`);return r===n?!1:(Bi(t,r,"utf-8"),!0)}function Fi(e){e.command("eject").description("Remove all GenerateSaaS ties - manifest, license, heartbeat, skills").action(async()=>{let t=process.cwd(),n=Ne(t,ge),r;try{r=JSON.parse(xn(n,"utf-8"))}catch{K.cancel("No GenerateSaaS project found in this directory."),process.exit(1)}let i=await K.text({message:'Type "eject" to confirm (this cannot be undone):',validate:s=>{if(s!=="eject")return'Type "eject" to confirm, or press Ctrl+C to cancel.'}});if(K.isCancel(i)&&(K.cancel("Eject cancelled."),process.exit(0)),r.licenseToken)try{await fetch("https://generatesaas.com/api/v1/heartbeat",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r.licenseToken}`},body:JSON.stringify({event:"eject",version:r.version,frontend:r.frontend}),signal:AbortSignal.timeout(5e3)}),K.log.info("Recorded the opt-out with generatesaas.com (final event - nothing is sent after this).")}catch{K.log.warn("Could not reach generatesaas.com to record the opt-out. Ejecting anyway.")}let o=[],a=[];for(let s of tc(r.aiTools))On(Ne(t,s))&&o.push(s);for(let s of Qs)On(Ne(t,s))&&o.push(s);On(Ne(t,z))&&o.push(z+"/");for(let s of ec){let d=Ne(t,s.file);nc(d,s.removals)?a.push(s.file):Gt(d)&&K.log.warn(`Could not auto-modify ${s.file} - manually remove license/heartbeat references.`)}rc(t)&&a.push(".gitignore");for(let s of o)K.log.info(`Deleted ${s}`);for(let s of a)K.log.info(`Modified ${s}`);K.log.success("Ejected successfully. This project is now fully standalone.")})}var Le=new ic().name("generatesaas").description("CLI for scaffolding and managing GenerateSaaS projects").version("1.23.1").addHelpText("after",`
|
|
1435
1436
|
Examples:
|
|
1436
1437
|
$ generatesaas init Interactive setup
|
|
1437
1438
|
$ generatesaas init -n my-app -y Quick setup with defaults
|