create-sailor 1.7.0 → 1.7.2

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.
Files changed (2) hide show
  1. package/dist/index.js +153 -152
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import{execSync as Rt}from"child_process";import _e from"fs";import de from"path";import*as O from"@clack/prompts";import{Command as Za}from"commander";import A from"picocolors";import ec from"update-notifier";import Ur from"cfonts";import Mr from"picocolors";import vn from"fs";import en from"path";import{fileURLToPath as Or}from"url";function Lr(){try{let t=en.dirname(Or(import.meta.url));for(let o=0;o<4;o++){let n=en.join(t,"package.json");if(vn.existsSync(n)){let r=vn.readFileSync(n,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=en.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var ae=Lr();function _n(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${ae}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
3
- `));return}Ur.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(Mr.dim(` AI-Native SaaS Template \xB7 v${ae} \xB7 nebutra.com
2
+ import{execSync as kt}from"child_process";import _e from"fs";import de from"path";import*as O from"@clack/prompts";import{Command as pc}from"commander";import A from"picocolors";import lc from"update-notifier";import Br from"cfonts";import Kr from"picocolors";import _n from"fs";import tn from"path";import{fileURLToPath as jr}from"url";function Vr(){try{let t=tn.dirname(jr(import.meta.url));for(let o=0;o<4;o++){let n=tn.join(t,"package.json");if(_n.existsSync(n)){let r=_n.readFileSync(n,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=tn.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var ae=Vr();function bn(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${ae}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
3
+ `));return}Br.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(Kr.dim(` AI-Native SaaS Template \xB7 v${ae} \xB7 nebutra.com
4
4
 
5
- `))}import P from"picocolors";var Dr={qstash:"foundation",bullmq:"foundation",upstash:"foundation",sqs:"foundation",meilisearch:"foundation",typesense:"foundation",algolia:"foundation",pgvector:"foundation",novu:"foundation",knock:"foundation",svix:"foundation","vercel-flags":"wip",growthbook:"wip",configcat:"wip",turnstile:"wip",hcaptcha:"wip","aliyun-slide":"wip",invite:"foundation"};function Fr(e){return e?Dr[e]??"stable":"stable"}function rt(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function me(e){switch(e){case"stable":return"Production-ready.";case"foundation":return"Foundation status \u2014 types + factory are complete, but provider adapters are stub-level and require external credentials.";case"wip":return"WIP \u2014 actively being built, should not be used in production.";case"deprecated":return"Deprecated \u2014 scheduled for removal, do not use."}}function bn(e){let t=[];for(let{flag:o,provider:n}of e){if(!n||n==="none")continue;let r=Fr(n);r!=="stable"&&t.push({flag:o,provider:n,status:r})}return t}function jr(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Pn(e){let t=jr(),o=t?"\u2693":"-",n=t?"\u25B8":"->",r=t?"\u2605":"*",s=t?"\u{1F4E7}":"*",c=["",` ${t?P.bold(`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`):`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`}`,"",` ${t?P.bold("Next:"):"Next:"}`,` ${n} cd ${e.targetDir}`];e.skippedInstall&&c.push(` ${n} pnpm install (if --no-install was set)`),c.push(` ${n} fill in .env.local ${t?P.dim("\u2192 add provider keys before booting apps"):"-> add provider keys before booting apps"}`,` ${n} pnpm db:migrate ${t?P.dim("\u2192 sync Prisma schema"):"-> sync Prisma schema"}`,` ${n} pnpm db:seed ${t?P.dim("\u2192 load example tenants and records"):"-> load example tenants and records"}`,` ${n} pnpm dev ${t?P.dim("\u2192 http://localhost:3000"):"-> http://localhost:3000"}`,"",` ${t?P.bold("Customize:"):"Customize:"}`,` ${n} pnpm brand:init ${t?P.dim("\u2192 create brand.config.ts"):"-> create brand.config.ts"}`,` ${n} pnpm brand:apply ${t?P.dim("\u2192 propagate brand changes"):"-> propagate brand changes"}`,` ${n} pnpm preset:env ${t?P.dim("\u2192 review preset env requirements"):"-> review preset env requirements"}`,"",` ${t?P.bold("Useful scripts:"):"Useful scripts:"}`,` ${n} pnpm infra:up ${t?P.dim("\u2192 start local PostgreSQL/Redis/ClickHouse"):"-> start local PostgreSQL/Redis/ClickHouse"}`,` ${n} pnpm generate:api-types ${t?P.dim("\u2192 refresh shared API client types"):"-> refresh shared API client types"}`,` ${n} pnpm lint ${t?P.dim("\u2192 quick repo sanity check"):"-> quick repo sanity check"}`,` ${n} pnpm audit ${t?P.dim("\u2192 scan deps for known CVEs"):"-> scan deps for known CVEs"}`);let a=e.previewSelections??[];if(a.length>0){let C=t?P.bold(P.yellow("\u26A0 Preview features selected:")):"!! Preview features selected:";c.push("",` ${C}`);for(let k of a){let $=rt(k.status),ue=` ${n} ${k.flag} (${k.provider}) ${$}`;c.push(t?P.yellow(ue):ue)}c.push("",` ${t?P.dim(me("foundation")):me("foundation")}`,` ${t?P.dim("You may need to contribute the provider integration yourself."):"You may need to contribute the provider integration yourself."}`,` ${t?P.dim("See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"):"See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"}`)}let l=e.waveFeatures??{},d=C=>C!==!1,S=[];d(l.apiKeys)&&S.push("Manage API keys at /settings/api-keys"),d(l.auditLog)&&S.push("View audit log at /settings/audit-log"),S.push("Configure webhooks at /settings/webhooks"),d(l.commandPalette)&&S.push("Press Cmd/Ctrl+K to open the command palette"),S.push("Edit notification preferences at /settings/notifications"),S.push("Export your data at /settings/account/export"),l.chinaCompliance&&S.push("China deployments \u2014 see packages/ops/china-compliance/README.md"),c.push("",` ${t?P.bold("What you can do next:"):"What you can do next:"}`);for(let C of S)c.push(` ${n} ${C}`);c.push("",` ${t?P.bold("Ship faster:"):"Ship faster:"}`,` ${r} Star us https://github.com/nebutra/nebutra-sailor`,` ${s} Free license https://nebutra.com/get-license`,""),process.stdout.write(c.join(`
5
+ `))}import P from"picocolors";var $r={qstash:"foundation",bullmq:"foundation",upstash:"foundation",sqs:"foundation",meilisearch:"foundation",typesense:"foundation",algolia:"foundation",pgvector:"foundation",novu:"foundation",knock:"foundation",svix:"foundation","vercel-flags":"wip",growthbook:"wip",configcat:"wip",turnstile:"wip",hcaptcha:"wip","aliyun-slide":"wip",invite:"foundation"};function Yr(e){return e?$r[e]??"stable":"stable"}function rt(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function me(e){switch(e){case"stable":return"Production-ready.";case"foundation":return"Foundation status \u2014 types + factory are complete, but provider adapters are stub-level and require external credentials.";case"wip":return"WIP \u2014 actively being built, should not be used in production.";case"deprecated":return"Deprecated \u2014 scheduled for removal, do not use."}}function Pn(e){let t=[];for(let{flag:o,provider:n}of e){if(!n||n==="none")continue;let r=Yr(n);r!=="stable"&&t.push({flag:o,provider:n,status:r})}return t}function qr(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function An(e){let t=qr(),o=t?"\u2693":"-",n=t?"\u25B8":"->",r=t?"\u2605":"*",s=t?"\u{1F4E7}":"*",c=["",` ${t?P.bold(`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`):`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`}`,"",` ${t?P.bold("Next:"):"Next:"}`,` ${n} cd ${e.targetDir}`];e.skippedInstall&&c.push(` ${n} pnpm install (if --no-install was set)`),c.push(` ${n} fill in .env.local ${t?P.dim("\u2192 add provider keys before booting apps"):"-> add provider keys before booting apps"}`,` ${n} pnpm db:migrate ${t?P.dim("\u2192 sync Prisma schema"):"-> sync Prisma schema"}`,` ${n} pnpm db:seed ${t?P.dim("\u2192 load example tenants and records"):"-> load example tenants and records"}`,` ${n} pnpm dev ${t?P.dim("\u2192 http://localhost:3000"):"-> http://localhost:3000"}`,"",` ${t?P.bold("Customize:"):"Customize:"}`,` ${n} pnpm brand:init ${t?P.dim("\u2192 create brand.config.ts"):"-> create brand.config.ts"}`,` ${n} pnpm brand:apply ${t?P.dim("\u2192 propagate brand changes"):"-> propagate brand changes"}`,` ${n} pnpm preset:env ${t?P.dim("\u2192 review preset env requirements"):"-> review preset env requirements"}`,"",` ${t?P.bold("Useful scripts:"):"Useful scripts:"}`,` ${n} pnpm infra:up ${t?P.dim("\u2192 start local PostgreSQL/Redis/ClickHouse"):"-> start local PostgreSQL/Redis/ClickHouse"}`,` ${n} pnpm generate:api-types ${t?P.dim("\u2192 refresh shared API client types"):"-> refresh shared API client types"}`,` ${n} pnpm lint ${t?P.dim("\u2192 quick repo sanity check"):"-> quick repo sanity check"}`,` ${n} pnpm audit ${t?P.dim("\u2192 scan deps for known CVEs"):"-> scan deps for known CVEs"}`);let a=e.previewSelections??[];if(a.length>0){let I=t?P.bold(P.yellow("\u26A0 Preview features selected:")):"!! Preview features selected:";c.push("",` ${I}`);for(let C of a){let U=rt(C.status),ue=` ${n} ${C.flag} (${C.provider}) ${U}`;c.push(t?P.yellow(ue):ue)}c.push("",` ${t?P.dim(me("foundation")):me("foundation")}`,` ${t?P.dim("You may need to contribute the provider integration yourself."):"You may need to contribute the provider integration yourself."}`,` ${t?P.dim("See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"):"See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"}`)}let l=e.waveFeatures??{},u=I=>I!==!1,S=[];u(l.apiKeys)&&S.push("Manage API keys at /settings/api-keys"),u(l.auditLog)&&S.push("View audit log at /settings/audit-log"),S.push("Configure webhooks at /settings/webhooks"),u(l.commandPalette)&&S.push("Press Cmd/Ctrl+K to open the command palette"),S.push("Edit notification preferences at /settings/notifications"),S.push("Export your data at /settings/account/export"),l.chinaCompliance&&S.push("China deployments \u2014 see packages/ops/china-compliance/README.md"),c.push("",` ${t?P.bold("What you can do next:"):"What you can do next:"}`);for(let I of S)c.push(` ${n} ${I}`);c.push("",` ${t?P.bold("Ship faster:"):"Ship faster:"}`,` ${r} Star us https://github.com/nebutra/nebutra-sailor`,` ${s} Free license https://nebutra.com/get-license`,""),process.stdout.write(c.join(`
6
6
  `)+`
7
- `)}var Vr=`Usage: create-sailor [name] [options]
7
+ `)}var Gr=`Usage: create-sailor [name] [options]
8
8
 
9
9
  Arguments:
10
10
  name project directory (default: ./my-saas-app)
@@ -74,9 +74,9 @@ Examples:
74
74
  $ npx create-sailor@latest my-app --region=cn --auth=clerk
75
75
  $ npx create-sailor@latest my-app --region=hybrid --ai=openai,deepseek
76
76
  $ npm create sailor@latest --dry-run --region=cn
77
- `;function An(){process.stdout.write(Vr)}import Lt from"picocolors";function Cn(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Br(e){let t=Cn()?"\u25B8":"->",o=`[${e.index}/${e.total}]`,n=e.label.padEnd(18," ");return Cn()?`${Lt.dim(o)} ${Lt.bold(n)} ${Lt.dim(t)} ${Lt.cyan(e.value)}`:`${o} ${n} ${t} ${e.value}`}function In(e){process.stdout.write(Br(e)+`
78
- `)}var tn=[{id:"anthropic",name:"Anthropic",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://docs.anthropic.com",envVarPrefix:"ANTHROPIC",requiredEnvVars:["ANTHROPIC_API_KEY"]},{id:"openai",name:"OpenAI",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.openai.com/docs",envVarPrefix:"OPENAI",requiredEnvVars:["OPENAI_API_KEY"]},{id:"deepseek",name:"DeepSeek",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.deepseek.com/api-docs",envVarPrefix:"DEEPSEEK",requiredEnvVars:["DEEPSEEK_API_KEY"]},{id:"xai",name:"xAI (Grok)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://docs.x.ai/api",envVarPrefix:"XAI",requiredEnvVars:["XAI_API_KEY"]},{id:"moonshot",name:"Moonshot (Kimi)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.moonshot.cn/docs",envVarPrefix:"MOONSHOT",requiredEnvVars:["MOONSHOT_API_KEY","MOONSHOT_BASE_URL"]},{id:"google",name:"Google Gemini",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://ai.google.dev/gemini-api/docs",envVarPrefix:"GOOGLE_GENERATIVE_AI",requiredEnvVars:["GOOGLE_GENERATIVE_AI_API_KEY"]},{id:"mistral",name:"Mistral AI",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://docs.mistral.ai",envVarPrefix:"MISTRAL",requiredEnvVars:["MISTRAL_API_KEY"]},{id:"cohere",name:"Cohere",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://docs.cohere.com",envVarPrefix:"COHERE",requiredEnvVars:["COHERE_API_KEY"]},{id:"perplexity",name:"Perplexity",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://docs.perplexity.ai",baseURL:"https://api.perplexity.ai",envVarPrefix:"PERPLEXITY",requiredEnvVars:["PERPLEXITY_API_KEY"]},{id:"ai21",name:"AI21 Labs",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://docs.ai21.com",baseURL:"https://api.ai21.com/studio/v1",envVarPrefix:"AI21",requiredEnvVars:["AI21_API_KEY"]},{id:"upstage",name:"Upstage (Solar)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://developers.upstage.ai/docs",baseURL:"https://api.upstage.ai/v1/solar",envVarPrefix:"UPSTAGE",requiredEnvVars:["UPSTAGE_API_KEY"]},{id:"siliconflow",name:"\u7845\u57FA\u6D41\u52A8 SiliconFlow",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://docs.siliconflow.cn",baseURL:"https://api.siliconflow.cn/v1",envVarPrefix:"SILICONFLOW",requiredEnvVars:["SILICONFLOW_API_KEY"]},{id:"volcengine-ark",name:"\u706B\u5C71\u5F15\u64CE ARK (\u8C46\u5305)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://www.volcengine.com/docs/82379",baseURL:"https://ark.cn-beijing.volces.com/api/v3",envVarPrefix:"ARK",requiredEnvVars:["ARK_API_KEY"]},{id:"bailian",name:"\u767E\u70BC Bailian (\u901A\u4E49)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://help.aliyun.com/zh/model-studio",baseURL:"https://dashscope.aliyuncs.com/compatible-mode/v1",envVarPrefix:"DASHSCOPE",requiredEnvVars:["DASHSCOPE_API_KEY"]},{id:"zhipu",name:"\u667A\u8C31 AI Zhipu",category:"\u56FD\u5185\u5E73\u53F0",status:"ai-sdk",docs:"https://docs.bigmodel.cn",baseURL:"https://open.bigmodel.cn/api/paas/v4",envVarPrefix:"ZHIPU",requiredEnvVars:["ZHIPU_API_KEY"]},{id:"baichuan",name:"\u767E\u5DDD\u667A\u80FD Baichuan",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.baichuan-ai.com/docs",baseURL:"https://api.baichuan-ai.com/v1",envVarPrefix:"BAICHUAN",requiredEnvVars:["BAICHUAN_API_KEY"]},{id:"minimax",name:"MiniMax (ABAB)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.minimaxi.com/document/guides",baseURL:"https://api.minimax.chat/v1",envVarPrefix:"MINIMAX",requiredEnvVars:["MINIMAX_API_KEY","MINIMAX_GROUP_ID"]},{id:"stepfun",name:"\u9636\u8DC3\u661F\u8FB0 StepFun",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.stepfun.com/docs",baseURL:"https://api.stepfun.com/v1",envVarPrefix:"STEPFUN",requiredEnvVars:["STEPFUN_API_KEY"]},{id:"sensetime",name:"\u5546\u6C64 SenseNova",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.sensetime.com",baseURL:"https://api.sensenova.cn/v1",envVarPrefix:"SENSENOVA",requiredEnvVars:["SENSENOVA_API_KEY"]},{id:"tencent",name:"\u817E\u8BAF\u6DF7\u5143 Hunyuan",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://cloud.tencent.com/document/product/1729",baseURL:"https://api.hunyuan.cloud.tencent.com/v1",envVarPrefix:"HUNYUAN",requiredEnvVars:["HUNYUAN_API_KEY"]},{id:"lingyi",name:"\u96F6\u4E00\u4E07\u7269 Yi",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.lingyiwanwu.com/docs",baseURL:"https://api.lingyiwanwu.com/v1",envVarPrefix:"YI",requiredEnvVars:["YI_API_KEY"]},{id:"openrouter",name:"OpenRouter",category:"\u7EDF\u4E00\u7F51\u5173",status:"opencode",docs:"https://openrouter.ai/docs",envVarPrefix:"OPENROUTER",requiredEnvVars:["OPENROUTER_API_KEY"]},{id:"vercel-gateway",name:"Vercel AI Gateway",category:"\u7EDF\u4E00\u7F51\u5173",status:"opencode",docs:"https://vercel.com/docs/ai-gateway",envVarPrefix:"AI_GATEWAY",requiredEnvVars:["AI_GATEWAY_API_KEY"]},{id:"litellm",name:"LiteLLM Proxy",category:"\u7EDF\u4E00\u7F51\u5173",status:"cn-compatible",docs:"https://docs.litellm.ai",baseURL:"http://localhost:4000/v1",envVarPrefix:"LITELLM",requiredEnvVars:["LITELLM_API_KEY"]},{id:"portkey",name:"Portkey",category:"\u7EDF\u4E00\u7F51\u5173",status:"cn-compatible",docs:"https://portkey.ai/docs",baseURL:"https://api.portkey.ai/v1",envVarPrefix:"PORTKEY",requiredEnvVars:["PORTKEY_API_KEY"]},{id:"aws-bedrock",name:"AWS Bedrock",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://aws.amazon.com/bedrock/",envVarPrefix:"AWS_BEDROCK",requiredEnvVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_REGION"]},{id:"azure-openai",name:"Azure OpenAI",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://azure.microsoft.com/en-us/products/cognitive-services/openai-service/",envVarPrefix:"AZURE_OPENAI",requiredEnvVars:["AZURE_OPENAI_API_KEY","AZURE_OPENAI_ENDPOINT"]},{id:"gcp-vertex",name:"GCP Vertex AI",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://cloud.google.com/vertex-ai",envVarPrefix:"GOOGLE_VERTEX",requiredEnvVars:["GOOGLE_APPLICATION_CREDENTIALS"]},{id:"groq",name:"Groq",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://console.groq.com/docs",envVarPrefix:"GROQ",requiredEnvVars:["GROQ_API_KEY"]},{id:"fireworks",name:"Fireworks AI",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://docs.fireworks.ai",envVarPrefix:"FIREWORKS",requiredEnvVars:["FIREWORKS_API_KEY"]},{id:"together",name:"Together AI",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://docs.together.ai",envVarPrefix:"TOGETHER",requiredEnvVars:["TOGETHER_API_KEY"]},{id:"huggingface",name:"Hugging Face",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://huggingface.co/docs/inference-providers",envVarPrefix:"HF",requiredEnvVars:["HF_API_KEY"]},{id:"replicate",name:"Replicate",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://replicate.com/docs",envVarPrefix:"REPLICATE",requiredEnvVars:["REPLICATE_API_TOKEN"]},{id:"lepton",name:"Lepton AI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://www.lepton.ai/docs",baseURL:"https://api.lepton.ai/v1",envVarPrefix:"LEPTON",requiredEnvVars:["LEPTON_API_KEY"]},{id:"anyscale",name:"Anyscale Endpoints",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://docs.endpoints.anyscale.com/",baseURL:"https://api.endpoints.anyscale.com/v1",envVarPrefix:"ANYSCALE",requiredEnvVars:["ANYSCALE_API_KEY"]},{id:"octoai",name:"OctoAI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://octoai.cloud/docs",baseURL:"https://text.octoai.run/v1",envVarPrefix:"OCTOAI",requiredEnvVars:["OCTOAI_TOKEN"]},{id:"deepinfra",name:"DeepInfra",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://deepinfra.com/docs",baseURL:"https://api.deepinfra.com/v1/openai",envVarPrefix:"DEEPINFRA",requiredEnvVars:["DEEPINFRA_API_KEY"]},{id:"novita",name:"Novita AI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://novita.ai/docs",baseURL:"https://api.novita.ai/v3/openai",envVarPrefix:"NOVITA",requiredEnvVars:["NOVITA_API_KEY"]},{id:"black-forest-labs",name:"Black Forest Labs (FLUX)",category:"\u591A\u6A21\u6001",status:"ai-sdk",docs:"https://docs.bfl.ml",envVarPrefix:"BFL",requiredEnvVars:["BFL_API_KEY"]},{id:"elevenlabs",name:"ElevenLabs (TTS)",category:"\u591A\u6A21\u6001",status:"ai-sdk",docs:"https://elevenlabs.io/docs",envVarPrefix:"ELEVENLABS",requiredEnvVars:["ELEVENLABS_API_KEY"]},{id:"runway",name:"Runway (Video)",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://runwayml.com",envVarPrefix:"RUNWAY",requiredEnvVars:["RUNWAY_API_KEY"]},{id:"luma",name:"Luma (Video)",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://lumalabs.ai",envVarPrefix:"LUMA",requiredEnvVars:["LUMA_API_KEY"]},{id:"midjourney",name:"Midjourney",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://docs.midjourney.com",envVarPrefix:"MIDJOURNEY",requiredEnvVars:[]},{id:"ollama",name:"Ollama (\u672C\u5730)",category:"\u672C\u5730\u90E8\u7F72",status:"opencode",docs:"https://github.com/ollama/ollama",baseURL:"http://localhost:11434/v1",envVarPrefix:"OLLAMA",requiredEnvVars:["OLLAMA_BASE_URL"]},{id:"lmstudio",name:"LM Studio",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://lmstudio.ai/docs",baseURL:"http://localhost:1234/v1",envVarPrefix:"LMSTUDIO",requiredEnvVars:[]},{id:"vllm",name:"vLLM",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://docs.vllm.ai",baseURL:"http://localhost:8000/v1",envVarPrefix:"VLLM",requiredEnvVars:[]},{id:"tgi",name:"HF TGI",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://huggingface.co/docs/text-generation-inference",baseURL:"http://localhost:8080/v1",envVarPrefix:"TGI",requiredEnvVars:[]}],_c=tn.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var Kr=["openai","anthropic","google"],$r=["openai"];function nn(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let o=t.length>0?t:[...Kr];return{mode:"gateway",providerIds:o,customEndpoint:e.customEndpoint,routing:{profile:"multi-provider-gateway",providerSeed:o,runtimeGovernance:!0}}}case"direct":{let o=t.length>0?t:[...$r];return{mode:"direct",providerIds:o,customEndpoint:e.customEndpoint,routing:{profile:"direct-adapters",providerSeed:o,runtimeGovernance:!1}}}case"custom":return{mode:"custom",providerIds:t,customEndpoint:e.customEndpoint,routing:{profile:"openai-compatible",providerSeed:t,runtimeGovernance:!0}};case"none":return{mode:"none",providerIds:[],routing:{profile:"disabled",providerSeed:[],runtimeGovernance:!1}}}}import st from"fs";import V from"path";var wn=[{id:"posthog",name:"PostHog",region:"both",envVars:["POSTHOG_KEY","NEXT_PUBLIC_POSTHOG_KEY","NEXT_PUBLIC_POSTHOG_HOST"],docs:"https://posthog.com/docs",pkgs:["posthog-js","posthog-node"],providerFile:"apps/web/src/lib/analytics/posthog.client.ts"},{id:"plausible",name:"Plausible",region:"global",envVars:["NEXT_PUBLIC_PLAUSIBLE_DOMAIN","NEXT_PUBLIC_PLAUSIBLE_SRC"],docs:"https://plausible.io/docs",providerFile:"apps/web/src/components/analytics/PlausibleScript.tsx"},{id:"umami",name:"Umami",region:"both",envVars:["NEXT_PUBLIC_UMAMI_WEBSITE_ID","NEXT_PUBLIC_UMAMI_SRC"],docs:"https://umami.is/docs",providerFile:"apps/web/src/components/analytics/UmamiScript.tsx"},{id:"mixpanel",name:"Mixpanel",region:"global",envVars:["MIXPANEL_TOKEN","NEXT_PUBLIC_MIXPANEL_TOKEN"],docs:"https://docs.mixpanel.com",pkgs:["mixpanel-browser","mixpanel"],providerFile:"apps/web/src/lib/analytics/mixpanel.client.ts"},{id:"baidu",name:"\u767E\u5EA6\u7EDF\u8BA1 Baidu Tongji",region:"cn",envVars:["NEXT_PUBLIC_BAIDU_STATS_ID"],docs:"https://tongji.baidu.com",providerFile:"apps/web/src/components/analytics/BaiduStatsScript.tsx"},{id:"sensors",name:"\u795E\u7B56 Sensors Analytics",region:"cn",envVars:["NEXT_PUBLIC_SENSORS_SERVER_URL","NEXT_PUBLIC_SENSORS_APP_JS_URL"],docs:"https://manual.sensorsdata.cn",pkgs:["sa-sdk-javascript"],providerFile:"apps/web/src/lib/analytics/sensors.client.ts"},{id:"growingio",name:"GrowingIO",region:"cn",envVars:["NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID"],docs:"https://growingio.com/docs",providerFile:"apps/web/src/components/analytics/GrowingIoScript.tsx"},{id:"none",name:"None",region:"both",envVars:[],docs:""}],Ac=wn.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Rn(e){return wn.find(t=>t.id===e)}function Yr(e){st.mkdirSync(e,{recursive:!0})}function Z(e,t){Yr(V.dirname(e)),st.writeFileSync(e,t)}function Ce(e,t){let o=V.join(e,".env.example");st.existsSync(o)?st.appendFileSync(o,`
79
- `+t):st.writeFileSync(o,t)}function qr(e){let t=`"use client";
77
+ `;function Cn(){process.stdout.write(Gr)}import Ut from"picocolors";function In(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Hr(e){let t=In()?"\u25B8":"->",o=`[${e.index}/${e.total}]`,n=e.label.padEnd(18," ");return In()?`${Ut.dim(o)} ${Ut.bold(n)} ${Ut.dim(t)} ${Ut.cyan(e.value)}`:`${o} ${n} ${t} ${e.value}`}function wn(e){process.stdout.write(Hr(e)+`
78
+ `)}var nn=[{id:"anthropic",name:"Anthropic",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://docs.anthropic.com",envVarPrefix:"ANTHROPIC",requiredEnvVars:["ANTHROPIC_API_KEY"]},{id:"openai",name:"OpenAI",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.openai.com/docs",envVarPrefix:"OPENAI",requiredEnvVars:["OPENAI_API_KEY"]},{id:"deepseek",name:"DeepSeek",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.deepseek.com/api-docs",envVarPrefix:"DEEPSEEK",requiredEnvVars:["DEEPSEEK_API_KEY"]},{id:"xai",name:"xAI (Grok)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://docs.x.ai/api",envVarPrefix:"XAI",requiredEnvVars:["XAI_API_KEY"]},{id:"moonshot",name:"Moonshot (Kimi)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.moonshot.cn/docs",envVarPrefix:"MOONSHOT",requiredEnvVars:["MOONSHOT_API_KEY","MOONSHOT_BASE_URL"]},{id:"google",name:"Google Gemini",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://ai.google.dev/gemini-api/docs",envVarPrefix:"GOOGLE_GENERATIVE_AI",requiredEnvVars:["GOOGLE_GENERATIVE_AI_API_KEY"]},{id:"mistral",name:"Mistral AI",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://docs.mistral.ai",envVarPrefix:"MISTRAL",requiredEnvVars:["MISTRAL_API_KEY"]},{id:"cohere",name:"Cohere",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://docs.cohere.com",envVarPrefix:"COHERE",requiredEnvVars:["COHERE_API_KEY"]},{id:"perplexity",name:"Perplexity",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://docs.perplexity.ai",baseURL:"https://api.perplexity.ai",envVarPrefix:"PERPLEXITY",requiredEnvVars:["PERPLEXITY_API_KEY"]},{id:"ai21",name:"AI21 Labs",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://docs.ai21.com",baseURL:"https://api.ai21.com/studio/v1",envVarPrefix:"AI21",requiredEnvVars:["AI21_API_KEY"]},{id:"upstage",name:"Upstage (Solar)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://developers.upstage.ai/docs",baseURL:"https://api.upstage.ai/v1/solar",envVarPrefix:"UPSTAGE",requiredEnvVars:["UPSTAGE_API_KEY"]},{id:"siliconflow",name:"\u7845\u57FA\u6D41\u52A8 SiliconFlow",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://docs.siliconflow.cn",baseURL:"https://api.siliconflow.cn/v1",envVarPrefix:"SILICONFLOW",requiredEnvVars:["SILICONFLOW_API_KEY"]},{id:"volcengine-ark",name:"\u706B\u5C71\u5F15\u64CE ARK (\u8C46\u5305)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://www.volcengine.com/docs/82379",baseURL:"https://ark.cn-beijing.volces.com/api/v3",envVarPrefix:"ARK",requiredEnvVars:["ARK_API_KEY"]},{id:"bailian",name:"\u767E\u70BC Bailian (\u901A\u4E49)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://help.aliyun.com/zh/model-studio",baseURL:"https://dashscope.aliyuncs.com/compatible-mode/v1",envVarPrefix:"DASHSCOPE",requiredEnvVars:["DASHSCOPE_API_KEY"]},{id:"zhipu",name:"\u667A\u8C31 AI Zhipu",category:"\u56FD\u5185\u5E73\u53F0",status:"ai-sdk",docs:"https://docs.bigmodel.cn",baseURL:"https://open.bigmodel.cn/api/paas/v4",envVarPrefix:"ZHIPU",requiredEnvVars:["ZHIPU_API_KEY"]},{id:"baichuan",name:"\u767E\u5DDD\u667A\u80FD Baichuan",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.baichuan-ai.com/docs",baseURL:"https://api.baichuan-ai.com/v1",envVarPrefix:"BAICHUAN",requiredEnvVars:["BAICHUAN_API_KEY"]},{id:"minimax",name:"MiniMax (ABAB)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.minimaxi.com/document/guides",baseURL:"https://api.minimax.chat/v1",envVarPrefix:"MINIMAX",requiredEnvVars:["MINIMAX_API_KEY","MINIMAX_GROUP_ID"]},{id:"stepfun",name:"\u9636\u8DC3\u661F\u8FB0 StepFun",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.stepfun.com/docs",baseURL:"https://api.stepfun.com/v1",envVarPrefix:"STEPFUN",requiredEnvVars:["STEPFUN_API_KEY"]},{id:"sensetime",name:"\u5546\u6C64 SenseNova",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.sensetime.com",baseURL:"https://api.sensenova.cn/v1",envVarPrefix:"SENSENOVA",requiredEnvVars:["SENSENOVA_API_KEY"]},{id:"tencent",name:"\u817E\u8BAF\u6DF7\u5143 Hunyuan",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://cloud.tencent.com/document/product/1729",baseURL:"https://api.hunyuan.cloud.tencent.com/v1",envVarPrefix:"HUNYUAN",requiredEnvVars:["HUNYUAN_API_KEY"]},{id:"lingyi",name:"\u96F6\u4E00\u4E07\u7269 Yi",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.lingyiwanwu.com/docs",baseURL:"https://api.lingyiwanwu.com/v1",envVarPrefix:"YI",requiredEnvVars:["YI_API_KEY"]},{id:"openrouter",name:"OpenRouter",category:"\u7EDF\u4E00\u7F51\u5173",status:"opencode",docs:"https://openrouter.ai/docs",envVarPrefix:"OPENROUTER",requiredEnvVars:["OPENROUTER_API_KEY"]},{id:"vercel-gateway",name:"Vercel AI Gateway",category:"\u7EDF\u4E00\u7F51\u5173",status:"opencode",docs:"https://vercel.com/docs/ai-gateway",envVarPrefix:"AI_GATEWAY",requiredEnvVars:["AI_GATEWAY_API_KEY"]},{id:"litellm",name:"LiteLLM Proxy",category:"\u7EDF\u4E00\u7F51\u5173",status:"cn-compatible",docs:"https://docs.litellm.ai",baseURL:"http://localhost:4000/v1",envVarPrefix:"LITELLM",requiredEnvVars:["LITELLM_API_KEY"]},{id:"portkey",name:"Portkey",category:"\u7EDF\u4E00\u7F51\u5173",status:"cn-compatible",docs:"https://portkey.ai/docs",baseURL:"https://api.portkey.ai/v1",envVarPrefix:"PORTKEY",requiredEnvVars:["PORTKEY_API_KEY"]},{id:"aws-bedrock",name:"AWS Bedrock",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://aws.amazon.com/bedrock/",envVarPrefix:"AWS_BEDROCK",requiredEnvVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_REGION"]},{id:"azure-openai",name:"Azure OpenAI",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://azure.microsoft.com/en-us/products/cognitive-services/openai-service/",envVarPrefix:"AZURE_OPENAI",requiredEnvVars:["AZURE_OPENAI_API_KEY","AZURE_OPENAI_ENDPOINT"]},{id:"gcp-vertex",name:"GCP Vertex AI",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://cloud.google.com/vertex-ai",envVarPrefix:"GOOGLE_VERTEX",requiredEnvVars:["GOOGLE_APPLICATION_CREDENTIALS"]},{id:"groq",name:"Groq",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://console.groq.com/docs",envVarPrefix:"GROQ",requiredEnvVars:["GROQ_API_KEY"]},{id:"fireworks",name:"Fireworks AI",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://docs.fireworks.ai",envVarPrefix:"FIREWORKS",requiredEnvVars:["FIREWORKS_API_KEY"]},{id:"together",name:"Together AI",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://docs.together.ai",envVarPrefix:"TOGETHER",requiredEnvVars:["TOGETHER_API_KEY"]},{id:"huggingface",name:"Hugging Face",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://huggingface.co/docs/inference-providers",envVarPrefix:"HF",requiredEnvVars:["HF_API_KEY"]},{id:"replicate",name:"Replicate",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://replicate.com/docs",envVarPrefix:"REPLICATE",requiredEnvVars:["REPLICATE_API_TOKEN"]},{id:"lepton",name:"Lepton AI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://www.lepton.ai/docs",baseURL:"https://api.lepton.ai/v1",envVarPrefix:"LEPTON",requiredEnvVars:["LEPTON_API_KEY"]},{id:"anyscale",name:"Anyscale Endpoints",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://docs.endpoints.anyscale.com/",baseURL:"https://api.endpoints.anyscale.com/v1",envVarPrefix:"ANYSCALE",requiredEnvVars:["ANYSCALE_API_KEY"]},{id:"octoai",name:"OctoAI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://octoai.cloud/docs",baseURL:"https://text.octoai.run/v1",envVarPrefix:"OCTOAI",requiredEnvVars:["OCTOAI_TOKEN"]},{id:"deepinfra",name:"DeepInfra",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://deepinfra.com/docs",baseURL:"https://api.deepinfra.com/v1/openai",envVarPrefix:"DEEPINFRA",requiredEnvVars:["DEEPINFRA_API_KEY"]},{id:"novita",name:"Novita AI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://novita.ai/docs",baseURL:"https://api.novita.ai/v3/openai",envVarPrefix:"NOVITA",requiredEnvVars:["NOVITA_API_KEY"]},{id:"black-forest-labs",name:"Black Forest Labs (FLUX)",category:"\u591A\u6A21\u6001",status:"ai-sdk",docs:"https://docs.bfl.ml",envVarPrefix:"BFL",requiredEnvVars:["BFL_API_KEY"]},{id:"elevenlabs",name:"ElevenLabs (TTS)",category:"\u591A\u6A21\u6001",status:"ai-sdk",docs:"https://elevenlabs.io/docs",envVarPrefix:"ELEVENLABS",requiredEnvVars:["ELEVENLABS_API_KEY"]},{id:"runway",name:"Runway (Video)",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://runwayml.com",envVarPrefix:"RUNWAY",requiredEnvVars:["RUNWAY_API_KEY"]},{id:"luma",name:"Luma (Video)",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://lumalabs.ai",envVarPrefix:"LUMA",requiredEnvVars:["LUMA_API_KEY"]},{id:"midjourney",name:"Midjourney",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://docs.midjourney.com",envVarPrefix:"MIDJOURNEY",requiredEnvVars:[]},{id:"ollama",name:"Ollama (\u672C\u5730)",category:"\u672C\u5730\u90E8\u7F72",status:"opencode",docs:"https://github.com/ollama/ollama",baseURL:"http://localhost:11434/v1",envVarPrefix:"OLLAMA",requiredEnvVars:["OLLAMA_BASE_URL"]},{id:"lmstudio",name:"LM Studio",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://lmstudio.ai/docs",baseURL:"http://localhost:1234/v1",envVarPrefix:"LMSTUDIO",requiredEnvVars:[]},{id:"vllm",name:"vLLM",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://docs.vllm.ai",baseURL:"http://localhost:8000/v1",envVarPrefix:"VLLM",requiredEnvVars:[]},{id:"tgi",name:"HF TGI",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://huggingface.co/docs/text-generation-inference",baseURL:"http://localhost:8080/v1",envVarPrefix:"TGI",requiredEnvVars:[]}],Nc=nn.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var Wr=["openai","anthropic","google"],Xr=["openai"];function on(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let o=t.length>0?t:[...Wr];return{mode:"gateway",providerIds:o,customEndpoint:e.customEndpoint,routing:{profile:"multi-provider-gateway",providerSeed:o,runtimeGovernance:!0}}}case"direct":{let o=t.length>0?t:[...Xr];return{mode:"direct",providerIds:o,customEndpoint:e.customEndpoint,routing:{profile:"direct-adapters",providerSeed:o,runtimeGovernance:!1}}}case"custom":return{mode:"custom",providerIds:t,customEndpoint:e.customEndpoint,routing:{profile:"openai-compatible",providerSeed:t,runtimeGovernance:!0}};case"none":return{mode:"none",providerIds:[],routing:{profile:"disabled",providerSeed:[],runtimeGovernance:!1}}}}import st from"fs";import B from"path";var Rn=[{id:"posthog",name:"PostHog",region:"both",envVars:["POSTHOG_KEY","NEXT_PUBLIC_POSTHOG_KEY","NEXT_PUBLIC_POSTHOG_HOST"],docs:"https://posthog.com/docs",pkgs:["posthog-js","posthog-node"],providerFile:"apps/web/src/lib/analytics/posthog.client.ts"},{id:"plausible",name:"Plausible",region:"global",envVars:["NEXT_PUBLIC_PLAUSIBLE_DOMAIN","NEXT_PUBLIC_PLAUSIBLE_SRC"],docs:"https://plausible.io/docs",providerFile:"apps/web/src/components/analytics/PlausibleScript.tsx"},{id:"umami",name:"Umami",region:"both",envVars:["NEXT_PUBLIC_UMAMI_WEBSITE_ID","NEXT_PUBLIC_UMAMI_SRC"],docs:"https://umami.is/docs",providerFile:"apps/web/src/components/analytics/UmamiScript.tsx"},{id:"mixpanel",name:"Mixpanel",region:"global",envVars:["MIXPANEL_TOKEN","NEXT_PUBLIC_MIXPANEL_TOKEN"],docs:"https://docs.mixpanel.com",pkgs:["mixpanel-browser","mixpanel"],providerFile:"apps/web/src/lib/analytics/mixpanel.client.ts"},{id:"baidu",name:"\u767E\u5EA6\u7EDF\u8BA1 Baidu Tongji",region:"cn",envVars:["NEXT_PUBLIC_BAIDU_STATS_ID"],docs:"https://tongji.baidu.com",providerFile:"apps/web/src/components/analytics/BaiduStatsScript.tsx"},{id:"sensors",name:"\u795E\u7B56 Sensors Analytics",region:"cn",envVars:["NEXT_PUBLIC_SENSORS_SERVER_URL","NEXT_PUBLIC_SENSORS_APP_JS_URL"],docs:"https://manual.sensorsdata.cn",pkgs:["sa-sdk-javascript"],providerFile:"apps/web/src/lib/analytics/sensors.client.ts"},{id:"growingio",name:"GrowingIO",region:"cn",envVars:["NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID"],docs:"https://growingio.com/docs",providerFile:"apps/web/src/components/analytics/GrowingIoScript.tsx"},{id:"none",name:"None",region:"both",envVars:[],docs:""}],Lc=Rn.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function kn(e){return Rn.find(t=>t.id===e)}function zr(e){st.mkdirSync(e,{recursive:!0})}function Z(e,t){zr(B.dirname(e)),st.writeFileSync(e,t)}function Ce(e,t){let o=B.join(e,".env.example");st.existsSync(o)?st.appendFileSync(o,`
79
+ `+t):st.writeFileSync(o,t)}function Jr(e){let t=`"use client";
80
80
  /**
81
81
  * PostHog browser SDK \u2014 lazy-initialized on first access.
82
82
  */
@@ -159,11 +159,11 @@ export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
159
159
 
160
160
  return <>{children}</>;
161
161
  }
162
- `;Z(V.join(e,"src","lib","analytics","posthog.client.ts"),t),Z(V.join(e,"src","lib","analytics","posthog.server.ts"),o),Z(V.join(e,"src","components","analytics","AnalyticsProvider.tsx"),n)}function Gr(){return`# PostHog \u2014 product analytics
162
+ `;Z(B.join(e,"src","lib","analytics","posthog.client.ts"),t),Z(B.join(e,"src","lib","analytics","posthog.server.ts"),o),Z(B.join(e,"src","components","analytics","AnalyticsProvider.tsx"),n)}function Qr(){return`# PostHog \u2014 product analytics
163
163
  POSTHOG_KEY=
164
164
  NEXT_PUBLIC_POSTHOG_KEY=
165
165
  NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
166
- `}function Hr(e){Z(V.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
166
+ `}function Zr(e){Z(B.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
167
167
  /**
168
168
  * Plausible script tag \u2014 lightweight, privacy-friendly analytics.
169
169
  */
@@ -183,10 +183,10 @@ export function PlausibleScript() {
183
183
  />
184
184
  );
185
185
  }
186
- `)}function Wr(){return`# Plausible \u2014 privacy-friendly analytics
186
+ `)}function es(){return`# Plausible \u2014 privacy-friendly analytics
187
187
  NEXT_PUBLIC_PLAUSIBLE_DOMAIN=
188
188
  NEXT_PUBLIC_PLAUSIBLE_SRC=https://plausible.io/js/script.js
189
- `}function Xr(e){Z(V.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
189
+ `}function ts(e){Z(B.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
190
190
  /**
191
191
  * Umami analytics \u2014 self-hosted OR umami.is cloud.
192
192
  */
@@ -206,10 +206,10 @@ export function UmamiScript() {
206
206
  />
207
207
  );
208
208
  }
209
- `)}function zr(){return`# Umami \u2014 self-hostable analytics
209
+ `)}function ns(){return`# Umami \u2014 self-hostable analytics
210
210
  NEXT_PUBLIC_UMAMI_WEBSITE_ID=
211
211
  NEXT_PUBLIC_UMAMI_SRC=https://cloud.umami.is/script.js
212
- `}function Jr(e){let t=`"use client";
212
+ `}function os(e){let t=`"use client";
213
213
  import mixpanel from "mixpanel-browser";
214
214
 
215
215
  let initialized = false;
@@ -248,10 +248,10 @@ export function trackServer(
248
248
  if (!c) return;
249
249
  c.track(event, { distinct_id: distinctId, ...properties });
250
250
  }
251
- `;Z(V.join(e,"src","lib","analytics","mixpanel.client.ts"),t),Z(V.join(e,"src","lib","analytics","mixpanel.server.ts"),o)}function Qr(){return`# Mixpanel \u2014 product analytics
251
+ `;Z(B.join(e,"src","lib","analytics","mixpanel.client.ts"),t),Z(B.join(e,"src","lib","analytics","mixpanel.server.ts"),o)}function rs(){return`# Mixpanel \u2014 product analytics
252
252
  MIXPANEL_TOKEN=
253
253
  NEXT_PUBLIC_MIXPANEL_TOKEN=
254
- `}function Zr(e){Z(V.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
254
+ `}function ss(e){Z(B.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
255
255
  /**
256
256
  * \u767E\u5EA6\u7EDF\u8BA1 Baidu Tongji \u2014 hm.js \u57CB\u70B9\u811A\u672C.
257
257
  */
@@ -277,9 +277,9 @@ var _hmt = _hmt || [];
277
277
  />
278
278
  );
279
279
  }
280
- `)}function es(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
280
+ `)}function is(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
281
281
  NEXT_PUBLIC_BAIDU_STATS_ID=
282
- `}function ts(e){Z(V.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
282
+ `}function as(e){Z(B.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
283
283
  /**
284
284
  * \u795E\u7B56\u5206\u6790 (Sensors Analytics) \u2014 sa-sdk-javascript \u5C01\u88C5.
285
285
  */
@@ -307,10 +307,10 @@ export function initSensors(): void {
307
307
  }
308
308
 
309
309
  export { sensors };
310
- `)}function ns(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
310
+ `)}function cs(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
311
311
  NEXT_PUBLIC_SENSORS_SERVER_URL=
312
312
  NEXT_PUBLIC_SENSORS_APP_JS_URL=
313
- `}function os(e){Z(V.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
313
+ `}function ps(e){Z(B.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
314
314
  /**
315
315
  * GrowingIO CDP \u2014 inline snippet installer.
316
316
  */
@@ -335,21 +335,21 @@ gdp("send");
335
335
  />
336
336
  );
337
337
  }
338
- `)}function rs(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
338
+ `)}function ls(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
339
339
  NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID=
340
- `}async function kn(e,t,o="global"){let n=Rn(t);if(!n||n.id==="none")return;let r=V.join(e,"apps","web");if(!st.existsSync(r))return;let s=n.id;try{switch(s){case"posthog":qr(r),Ce(e,Gr());return;case"plausible":Hr(r),Ce(e,Wr());return;case"umami":Xr(r),Ce(e,zr());return;case"mixpanel":Jr(r),Ce(e,Qr());return;case"baidu":Zr(r),Ce(e,es());return;case"sensors":ts(r),Ce(e,ns());return;case"growingio":os(r),Ce(e,rs());return;default:return}}catch(i){throw console.error(`Failed to apply analytics selection "${t}":`,i),new Error(`Analytics scaffold for "${t}" failed \u2014 see stderr for details.`)}}var ss="https://analytics.nebutra.com";function is(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function xn(e,t={}){is(t)||(async()=>{try{let o=await import("@nebutra/analytics");if(typeof o.createAnalyticsClient!="function")return;let n=o.createAnalyticsClient({posthog:{apiKey:process.env.NEBUTRA_POSTHOG_KEY??"",host:process.env.NEBUTRA_POSTHOG_HOST??ss},onError:()=>{}});if(typeof n?.track!="function")return;let r=n.track("scaffold.completed",e);r&&typeof r.then=="function"&&await r.catch(()=>{})}catch{}})()}import q from"fs";import x from"path";function B(e){q.existsSync(e)&&q.rmSync(e,{recursive:!0,force:!0})}function Ut(e,t){let o=x.join(e,".env.example");q.existsSync(o)?q.appendFileSync(o,`
341
- `+t):q.writeFileSync(o,t)}function Mt(e,t){if(!q.existsSync(e))return;let o=q.readFileSync(e,"utf8"),n=o.replace(/export type AuthProviderId\s*=\s*(?:"[^"]+"\s*\|\s*)+"[^"]+";/,`export type AuthProviderId = "${t}";`);n!==o&&q.writeFileSync(e,n)}function as(e,t){let o=x.join(e,"README.md");if(!q.existsSync(o)){q.writeFileSync(o,t);return}q.appendFileSync(o,`
342
- `+t)}async function Nn(e,t){let o=x.join(e,"packages","iam","auth");if(!q.existsSync(o))return;if(t==="none"){B(o),as(e,`
340
+ `}async function xn(e,t,o="global"){let n=kn(t);if(!n||n.id==="none")return;let r=B.join(e,"apps","web");if(!st.existsSync(r))return;let s=n.id;try{switch(s){case"posthog":Jr(r),Ce(e,Qr());return;case"plausible":Zr(r),Ce(e,es());return;case"umami":ts(r),Ce(e,ns());return;case"mixpanel":os(r),Ce(e,rs());return;case"baidu":ss(r),Ce(e,is());return;case"sensors":as(r),Ce(e,cs());return;case"growingio":ps(r),Ce(e,ls());return;default:return}}catch(i){throw console.error(`Failed to apply analytics selection "${t}":`,i),new Error(`Analytics scaffold for "${t}" failed \u2014 see stderr for details.`)}}var ds="https://analytics.nebutra.com";function us(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function Nn(e,t={}){us(t)||(async()=>{try{let o=await import("@nebutra/analytics");if(typeof o.createAnalyticsClient!="function")return;let n=o.createAnalyticsClient({posthog:{apiKey:process.env.NEBUTRA_POSTHOG_KEY??"",host:process.env.NEBUTRA_POSTHOG_HOST??ds},onError:()=>{}});if(typeof n?.track!="function")return;let r=n.track("scaffold.completed",e);r&&typeof r.then=="function"&&await r.catch(()=>{})}catch{}})()}import q from"fs";import x from"path";function K(e){q.existsSync(e)&&q.rmSync(e,{recursive:!0,force:!0})}function Mt(e,t){let o=x.join(e,".env.example");q.existsSync(o)?q.appendFileSync(o,`
341
+ `+t):q.writeFileSync(o,t)}function Dt(e,t){if(!q.existsSync(e))return;let o=q.readFileSync(e,"utf8"),n=o.replace(/export type AuthProviderId\s*=\s*(?:"[^"]+"\s*\|\s*)+"[^"]+";/,`export type AuthProviderId = "${t}";`);n!==o&&q.writeFileSync(e,n)}function ms(e,t){let o=x.join(e,"README.md");if(!q.existsSync(o)){q.writeFileSync(o,t);return}q.appendFileSync(o,`
342
+ `+t)}async function Tn(e,t){let o=x.join(e,"packages","iam","auth");if(!q.existsSync(o))return;if(t==="none"){K(o),ms(e,`
343
343
  ## Auth
344
344
 
345
345
  Auth was skipped at scaffold time (\`--auth=none\`). Add your preferred auth provider manually (e.g. Clerk, Better Auth, NextAuth, Supabase).
346
- `);return}let n=x.join(o,"src","providers"),r=x.join(o,"src","types.ts");if(t==="clerk"){B(x.join(n,"better-auth.ts")),B(x.join(n,"nextauth.ts")),B(x.join(n,"supabase.ts")),Mt(r,"clerk"),Ut(e,`# Clerk auth
346
+ `);return}let n=x.join(o,"src","providers"),r=x.join(o,"src","types.ts");if(t==="clerk"){K(x.join(n,"better-auth.ts")),K(x.join(n,"nextauth.ts")),K(x.join(n,"supabase.ts")),Dt(r,"clerk"),Mt(e,`# Clerk auth
347
347
  CLERK_PUBLISHABLE_KEY=
348
348
  CLERK_SECRET_KEY=
349
- `);return}if(t==="betterauth"){B(x.join(n,"clerk.ts")),B(x.join(n,"nextauth.ts")),B(x.join(n,"supabase.ts")),Mt(r,"better-auth"),Ut(e,`# Better Auth
349
+ `);return}if(t==="betterauth"){K(x.join(n,"clerk.ts")),K(x.join(n,"nextauth.ts")),K(x.join(n,"supabase.ts")),Dt(r,"better-auth"),Mt(e,`# Better Auth
350
350
  BETTER_AUTH_SECRET=
351
351
  BETTER_AUTH_URL=http://localhost:3000
352
- `);return}if(t==="nextauth"){B(x.join(n,"clerk.ts")),B(x.join(n,"better-auth.ts")),B(x.join(n,"supabase.ts")),Mt(r,"nextauth"),Ut(e,`# NextAuth (Auth.js v5)
352
+ `);return}if(t==="nextauth"){K(x.join(n,"clerk.ts")),K(x.join(n,"better-auth.ts")),K(x.join(n,"supabase.ts")),Dt(r,"nextauth"),Mt(e,`# NextAuth (Auth.js v5)
353
353
  AUTH_SECRET=
354
354
  NEXTAUTH_URL=http://localhost:3000
355
355
  # OAuth (optional \u2014 leave blank to disable that provider)
@@ -357,13 +357,13 @@ GOOGLE_CLIENT_ID=
357
357
  GOOGLE_CLIENT_SECRET=
358
358
  GITHUB_CLIENT_ID=
359
359
  GITHUB_CLIENT_SECRET=
360
- `);return}if(t==="supabase"){B(x.join(n,"clerk.ts")),B(x.join(n,"better-auth.ts")),B(x.join(n,"nextauth.ts")),Mt(r,"supabase"),Ut(e,`# Supabase Auth
360
+ `);return}if(t==="supabase"){K(x.join(n,"clerk.ts")),K(x.join(n,"better-auth.ts")),K(x.join(n,"nextauth.ts")),Dt(r,"supabase"),Mt(e,`# Supabase Auth
361
361
  NEXT_PUBLIC_SUPABASE_URL=
362
362
  NEXT_PUBLIC_SUPABASE_ANON_KEY=
363
363
  SUPABASE_URL=
364
364
  SUPABASE_ANON_KEY=
365
365
  SUPABASE_SERVICE_ROLE_KEY=
366
- `);return}}var Et=[{id:"wechat",name:"\u5FAE\u4FE1\u5F00\u653E\u5E73\u53F0",region:"cn",envVars:["WECHAT_APP_ID","WECHAT_APP_SECRET"],docs:"https://open.weixin.qq.com/cgi-bin/showdocument",callbackUrl:"/api/auth/callback/wechat",tokenEndpoint:"https://api.weixin.qq.com/sns/oauth2/access_token"},{id:"qq",name:"QQ \u767B\u5F55",region:"cn",envVars:["QQ_APP_ID","QQ_APP_KEY"],docs:"https://wiki.connect.qq.com",callbackUrl:"/api/auth/callback/qq",tokenEndpoint:"https://graph.qq.com/oauth2.0/token"},{id:"dingtalk",name:"\u9489\u9489",region:"cn",envVars:["DINGTALK_APP_ID","DINGTALK_APP_SECRET"],docs:"https://open.dingtalk.com/document/",callbackUrl:"/api/auth/callback/dingtalk",tokenEndpoint:"https://api.dingtalk.com/v1.0/oauth2/userAccessToken"},{id:"workweixin",name:"\u4F01\u4E1A\u5FAE\u4FE1",region:"cn",envVars:["WORKWEIXIN_CORP_ID","WORKWEIXIN_AGENT_ID","WORKWEIXIN_SECRET"],docs:"https://developer.work.weixin.qq.com",callbackUrl:"/api/auth/callback/workweixin",tokenEndpoint:"https://qyapi.weixin.qq.com/cgi-bin/gettoken"},{id:"feishu",name:"\u98DE\u4E66 / Lark",region:"cn",envVars:["FEISHU_APP_ID","FEISHU_APP_SECRET"],docs:"https://open.feishu.cn/document/",callbackUrl:"/api/auth/callback/feishu",tokenEndpoint:"https://open.feishu.cn/open-apis/authen/v1/access_token"},{id:"weibo",name:"\u5FAE\u535A",region:"cn",envVars:["WEIBO_APP_KEY","WEIBO_APP_SECRET"],docs:"https://open.weibo.com/wiki/",callbackUrl:"/api/auth/callback/weibo",tokenEndpoint:"https://api.weibo.com/oauth2/access_token"}],cs=new Set(Et.map(e=>e.id));function Tn(e){return Et.find(t=>t.id===e)}function On(e){if(!e)return[];let t=e.split(",").map(r=>r.trim().toLowerCase()).filter(Boolean);if(t.includes("none"))return[];let o=[],n=new Set;for(let r of t)cs.has(r)&&!n.has(r)&&(o.push(r),n.add(r));return o}import we from"fs";import Ie from"path";function ps(e,t){let o=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
366
+ `);return}}var Et=[{id:"wechat",name:"\u5FAE\u4FE1\u5F00\u653E\u5E73\u53F0",region:"cn",envVars:["WECHAT_APP_ID","WECHAT_APP_SECRET"],docs:"https://open.weixin.qq.com/cgi-bin/showdocument",callbackUrl:"/api/auth/callback/wechat",tokenEndpoint:"https://api.weixin.qq.com/sns/oauth2/access_token"},{id:"qq",name:"QQ \u767B\u5F55",region:"cn",envVars:["QQ_APP_ID","QQ_APP_KEY"],docs:"https://wiki.connect.qq.com",callbackUrl:"/api/auth/callback/qq",tokenEndpoint:"https://graph.qq.com/oauth2.0/token"},{id:"dingtalk",name:"\u9489\u9489",region:"cn",envVars:["DINGTALK_APP_ID","DINGTALK_APP_SECRET"],docs:"https://open.dingtalk.com/document/",callbackUrl:"/api/auth/callback/dingtalk",tokenEndpoint:"https://api.dingtalk.com/v1.0/oauth2/userAccessToken"},{id:"workweixin",name:"\u4F01\u4E1A\u5FAE\u4FE1",region:"cn",envVars:["WORKWEIXIN_CORP_ID","WORKWEIXIN_AGENT_ID","WORKWEIXIN_SECRET"],docs:"https://developer.work.weixin.qq.com",callbackUrl:"/api/auth/callback/workweixin",tokenEndpoint:"https://qyapi.weixin.qq.com/cgi-bin/gettoken"},{id:"feishu",name:"\u98DE\u4E66 / Lark",region:"cn",envVars:["FEISHU_APP_ID","FEISHU_APP_SECRET"],docs:"https://open.feishu.cn/document/",callbackUrl:"/api/auth/callback/feishu",tokenEndpoint:"https://open.feishu.cn/open-apis/authen/v1/access_token"},{id:"weibo",name:"\u5FAE\u535A",region:"cn",envVars:["WEIBO_APP_KEY","WEIBO_APP_SECRET"],docs:"https://open.weibo.com/wiki/",callbackUrl:"/api/auth/callback/weibo",tokenEndpoint:"https://api.weibo.com/oauth2/access_token"}],gs=new Set(Et.map(e=>e.id));function On(e){return Et.find(t=>t.id===e)}function Ln(e){if(!e)return[];let t=e.split(",").map(r=>r.trim().toLowerCase()).filter(Boolean);if(t.includes("none"))return[];let o=[],n=new Set;for(let r of t)gs.has(r)&&!n.has(r)&&(o.push(r),n.add(r));return o}import we from"fs";import Ie from"path";function fs(e,t){let o=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
367
367
  // Generated by create-sailor \u2014 OAuth callback for ${e.name}
368
368
  // Primary auth provider: ${t}
369
369
  // Docs: ${e.docs}`,n={wechat:` const tokenRes = await fetch(
@@ -488,7 +488,7 @@ ${n[e.id]}
488
488
  void state;
489
489
  return NextResponse.redirect(new URL("/dashboard", req.url));
490
490
  }
491
- `}function ls(e){return`"use client";
491
+ `}function ys(e){return`"use client";
492
492
 
493
493
  /**
494
494
  * SocialLoginButtons \u2014 generated by create-sailor.
@@ -531,23 +531,23 @@ export function SocialLoginButtons() {
531
531
  </div>
532
532
  );
533
533
  }
534
- `}function Ln(e){we.mkdirSync(e,{recursive:!0})}function ds(e,t){let o=Ie.join(e,".env.example");we.existsSync(o)?we.appendFileSync(o,`
535
- `+t):we.writeFileSync(o,t)}function us(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,o=e.envVars.map(n=>`${n}=`).join(`
534
+ `}function Un(e){we.mkdirSync(e,{recursive:!0})}function Ss(e,t){let o=Ie.join(e,".env.example");we.existsSync(o)?we.appendFileSync(o,`
535
+ `+t):we.writeFileSync(o,t)}function hs(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,o=e.envVars.map(n=>`${n}=`).join(`
536
536
  `);return`${t}
537
537
  ${o}
538
- `}async function Un(e,t,o){if(!t||t.length===0)return;let n=Ie.join(e,"apps","web");if(!we.existsSync(n))return;let r=new Set,s=[];for(let l of t){if(r.has(l))continue;r.add(l);let d=Tn(l);d&&s.push(d)}if(s.length===0)return;for(let l of s)ds(e,us(l));let i=Ie.join(n,"src","app","api","auth","callback");for(let l of s){let d=Ie.join(i,l.id);Ln(d);let S=Ie.join(d,"route.ts");we.writeFileSync(S,ps(l,o))}let c=Ie.join(n,"src","components","auth");Ln(c);let a=Ie.join(c,"SocialLoginButtons.tsx");we.writeFileSync(a,ls(s))}import it from"fs";import Dn from"path";var Dt=[{id:"upstash-redis",name:"Upstash Redis",region:"both",envVars:["UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN"],docs:"https://upstash.com/docs/redis",description:"Serverless Redis"},{id:"vercel-kv",name:"Vercel KV",region:"global",envVars:["KV_URL","KV_REST_API_URL","KV_REST_API_TOKEN","KV_REST_API_READ_ONLY_TOKEN"],docs:"https://vercel.com/docs/storage/vercel-kv",description:"Vercel native KV"},{id:"redis",name:"Redis (self-hosted)",region:"both",envVars:["REDIS_URL"],docs:"https://redis.io/docs/",description:"Self-hosted Redis"},{id:"dragonfly",name:"Dragonfly",region:"global",envVars:["DRAGONFLY_URL"],docs:"https://www.dragonflydb.io/docs",description:"Drop-in Redis replacement, faster"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip cache package"}];function Mn(e){return Dt.find(t=>t.id===e)}var jc=Dt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import ee from"fs";import Ft from"path";function te(e,t){let o=Ft.join(e,".env.example");if(!ee.existsSync(o)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(ee.readFileSync(o,"utf-8").includes(r))return;let c=["","# =============================================",r,t.docs?`# Docs: ${t.docs}`:null,"# =============================================",...t.envVars.map(a=>`${a}=""`),""].filter(a=>a!==null).join(`
539
- `);ee.appendFileSync(o,c)}function ne(e,t,o){let n=Ft.join(e,".env.example");if(!ee.existsSync(n))return;let r=ee.readFileSync(n,"utf-8"),s=`${t}="${o}"`,i=new RegExp(`^${t}=.*$`,"m");if(i.test(r)){ee.writeFileSync(n,r.replace(i,s));return}let c=r.endsWith(`
538
+ `}async function Mn(e,t,o){if(!t||t.length===0)return;let n=Ie.join(e,"apps","web");if(!we.existsSync(n))return;let r=new Set,s=[];for(let l of t){if(r.has(l))continue;r.add(l);let u=On(l);u&&s.push(u)}if(s.length===0)return;for(let l of s)Ss(e,hs(l));let i=Ie.join(n,"src","app","api","auth","callback");for(let l of s){let u=Ie.join(i,l.id);Un(u);let S=Ie.join(u,"route.ts");we.writeFileSync(S,fs(l,o))}let c=Ie.join(n,"src","components","auth");Un(c);let a=Ie.join(c,"SocialLoginButtons.tsx");we.writeFileSync(a,ys(s))}import it from"fs";import Fn from"path";var Ft=[{id:"upstash-redis",name:"Upstash Redis",region:"both",envVars:["UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN"],docs:"https://upstash.com/docs/redis",description:"Serverless Redis"},{id:"vercel-kv",name:"Vercel KV",region:"global",envVars:["KV_URL","KV_REST_API_URL","KV_REST_API_TOKEN","KV_REST_API_READ_ONLY_TOKEN"],docs:"https://vercel.com/docs/storage/vercel-kv",description:"Vercel native KV"},{id:"redis",name:"Redis (self-hosted)",region:"both",envVars:["REDIS_URL"],docs:"https://redis.io/docs/",description:"Self-hosted Redis"},{id:"dragonfly",name:"Dragonfly",region:"global",envVars:["DRAGONFLY_URL"],docs:"https://www.dragonflydb.io/docs",description:"Drop-in Redis replacement, faster"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip cache package"}];function Dn(e){return Ft.find(t=>t.id===e)}var Xc=Ft.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import ee from"fs";import jt from"path";function te(e,t){let o=jt.join(e,".env.example");if(!ee.existsSync(o)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(ee.readFileSync(o,"utf-8").includes(r))return;let c=["","# =============================================",r,t.docs?`# Docs: ${t.docs}`:null,"# =============================================",...t.envVars.map(a=>`${a}=""`),""].filter(a=>a!==null).join(`
539
+ `);ee.appendFileSync(o,c)}function ne(e,t,o){let n=jt.join(e,".env.example");if(!ee.existsSync(n))return;let r=ee.readFileSync(n,"utf-8"),s=`${t}="${o}"`,i=new RegExp(`^${t}=.*$`,"m");if(i.test(r)){ee.writeFileSync(n,r.replace(i,s));return}let c=r.endsWith(`
540
540
  `)?"":`
541
541
  `;ee.appendFileSync(n,`${c}${s}
542
- `)}var ms=["design","iam","commerce","integrations","platform","ops","ai"];function Re(e,t){for(let n of ms){let r=Ft.join(e,"packages",n,t);if(ee.existsSync(r))return r}let o=Ft.join(e,"packages",t);return ee.existsSync(o)?o:null}function X(e,t){let o=Re(e,t);o&&ee.rmSync(o,{recursive:!0,force:!0})}function Fn(e){return it.existsSync(e)?it.readFileSync(e,"utf-8"):null}function gs(e,t){let o=Dn.join(e,".env.example"),n=Fn(o);if(n===null)return;let r=`# Cache: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
543
- `);it.appendFileSync(o,s)}function fs(e,t,o){let n=Dn.join(e,".env.example"),r=Fn(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?it.writeFileSync(n,r.replace(s,`${t}="${o}"`)):it.appendFileSync(n,`${t}="${o}"
544
- `)}async function jn(e,t,o){let n=Re(e,"cache");if(t==="none"){n&&it.rmSync(n,{recursive:!0,force:!0});return}let r=Mn(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${Dt.map(s=>s.id).join(", ")}`);n&&(gs(e,r),fs(e,"CACHE_PROVIDER",t))}var jt=[{id:"turnstile",name:"Cloudflare Turnstile",region:"global",envVars:["NEXT_PUBLIC_TURNSTILE_SITE_KEY","TURNSTILE_SECRET_KEY"],docs:"https://developers.cloudflare.com/turnstile/",description:"Free, privacy-focused captcha alternative"},{id:"hcaptcha",name:"hCaptcha",region:"global",envVars:["NEXT_PUBLIC_HCAPTCHA_SITE_KEY","HCAPTCHA_SECRET_KEY"],docs:"https://docs.hcaptcha.com/",description:"Privacy-respecting captcha"},{id:"aliyun-slide",name:"\u963F\u91CC\u4E91\u9A8C\u8BC1\u7801 2.0",region:"cn",envVars:["ALIYUN_CAPTCHA_ACCESS_KEY_ID","ALIYUN_CAPTCHA_ACCESS_KEY_SECRET","ALIYUN_CAPTCHA_APP_KEY","NEXT_PUBLIC_ALIYUN_CAPTCHA_APP_KEY"],docs:"https://help.aliyun.com/product/28308.html",description:"\u963F\u91CC\u4E91\u667A\u80FD\u9A8C\u8BC1 (\u6ED1\u5757/\u65E0\u75D5)"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Vn(e){return jt.find(t=>t.id===e)}var Xc=jt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Bn(e,t,o="global"){let n=Vn(t);if(!n)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${jt.map(r=>r.id).join(", ")}`);if(n.id==="none"){X(e,"captcha");return}n.envVars.length>0&&te(e,{category:"Captcha",name:n.name,envVars:n.envVars,docs:n.docs}),ne(e,"CAPTCHA_PROVIDER",n.id)}import Bt from"fs";import ys from"path";var Vt=[{id:"sanity",name:"Sanity",region:"global",envVars:["SANITY_PROJECT_ID","SANITY_DATASET","SANITY_API_TOKEN","SANITY_API_VERSION"],docs:"https://www.sanity.io/docs",description:"Structured content platform with Studio"},{id:"contentful",name:"Contentful",region:"global",envVars:["CONTENTFUL_SPACE_ID","CONTENTFUL_ACCESS_TOKEN","CONTENTFUL_PREVIEW_ACCESS_TOKEN"],docs:"https://www.contentful.com/developers/docs/",description:"Headless CMS"},{id:"strapi",name:"Strapi",region:"both",envVars:["STRAPI_URL","STRAPI_API_TOKEN"],docs:"https://docs.strapi.io",description:"Open-source self-hosted CMS"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Kn(e){return Vt.find(t=>t.id===e)}var ep=Vt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function $n(e,t,o="global"){let n=Kn(t);if(!n)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${Vt.map(s=>s.id).join(", ")}`);let r=ys.join(e,"apps","studio");if(n.id==="none"){X(e,"sanity"),Bt.existsSync(r)&&Bt.rmSync(r,{recursive:!0,force:!0});return}n.id!=="sanity"&&(X(e,"sanity"),Bt.existsSync(r)&&Bt.rmSync(r,{recursive:!0,force:!0})),n.envVars.length>0&&te(e,{category:"CMS",name:n.name,envVars:n.envVars,docs:n.docs}),ne(e,"CMS_PROVIDER",n.id)}import T from"fs";import N from"path";var Ss=N.join("apps","web"),on=N.join("src","components","compliance"),vt=N.join("src","app","[locale]");function oe(e){return N.join(e,Ss)}function hs(e){T.mkdirSync(e,{recursive:!0})}function z(e,t){hs(N.dirname(e)),T.writeFileSync(e,t,"utf8")}function rn(e,t){let o=N.join(e,".env.example");if(T.existsSync(o)){if(T.readFileSync(o,"utf8").includes(t.split(`
542
+ `)}var Es=["design","iam","commerce","integrations","platform","ops","ai"];function Re(e,t){for(let n of Es){let r=jt.join(e,"packages",n,t);if(ee.existsSync(r))return r}let o=jt.join(e,"packages",t);return ee.existsSync(o)?o:null}function X(e,t){let o=Re(e,t);o&&ee.rmSync(o,{recursive:!0,force:!0})}function jn(e){return it.existsSync(e)?it.readFileSync(e,"utf-8"):null}function vs(e,t){let o=Fn.join(e,".env.example"),n=jn(o);if(n===null)return;let r=`# Cache: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
543
+ `);it.appendFileSync(o,s)}function _s(e,t,o){let n=Fn.join(e,".env.example"),r=jn(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?it.writeFileSync(n,r.replace(s,`${t}="${o}"`)):it.appendFileSync(n,`${t}="${o}"
544
+ `)}async function Vn(e,t,o){let n=Re(e,"cache");if(t==="none"){n&&it.rmSync(n,{recursive:!0,force:!0});return}let r=Dn(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${Ft.map(s=>s.id).join(", ")}`);n&&(vs(e,r),_s(e,"CACHE_PROVIDER",t))}var Vt=[{id:"turnstile",name:"Cloudflare Turnstile",region:"global",envVars:["NEXT_PUBLIC_TURNSTILE_SITE_KEY","TURNSTILE_SECRET_KEY"],docs:"https://developers.cloudflare.com/turnstile/",description:"Free, privacy-focused captcha alternative"},{id:"hcaptcha",name:"hCaptcha",region:"global",envVars:["NEXT_PUBLIC_HCAPTCHA_SITE_KEY","HCAPTCHA_SECRET_KEY"],docs:"https://docs.hcaptcha.com/",description:"Privacy-respecting captcha"},{id:"aliyun-slide",name:"\u963F\u91CC\u4E91\u9A8C\u8BC1\u7801 2.0",region:"cn",envVars:["ALIYUN_CAPTCHA_ACCESS_KEY_ID","ALIYUN_CAPTCHA_ACCESS_KEY_SECRET","ALIYUN_CAPTCHA_APP_KEY","NEXT_PUBLIC_ALIYUN_CAPTCHA_APP_KEY"],docs:"https://help.aliyun.com/product/28308.html",description:"\u963F\u91CC\u4E91\u667A\u80FD\u9A8C\u8BC1 (\u6ED1\u5757/\u65E0\u75D5)"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Bn(e){return Vt.find(t=>t.id===e)}var sp=Vt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Kn(e,t,o="global"){let n=Bn(t);if(!n)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${Vt.map(r=>r.id).join(", ")}`);if(n.id==="none"){X(e,"captcha");return}n.envVars.length>0&&te(e,{category:"Captcha",name:n.name,envVars:n.envVars,docs:n.docs}),ne(e,"CAPTCHA_PROVIDER",n.id)}import Kt from"fs";import bs from"path";var Bt=[{id:"sanity",name:"Sanity",region:"global",envVars:["SANITY_PROJECT_ID","SANITY_DATASET","SANITY_API_TOKEN","SANITY_API_VERSION"],docs:"https://www.sanity.io/docs",description:"Structured content platform with Studio"},{id:"contentful",name:"Contentful",region:"global",envVars:["CONTENTFUL_SPACE_ID","CONTENTFUL_ACCESS_TOKEN","CONTENTFUL_PREVIEW_ACCESS_TOKEN"],docs:"https://www.contentful.com/developers/docs/",description:"Headless CMS"},{id:"strapi",name:"Strapi",region:"both",envVars:["STRAPI_URL","STRAPI_API_TOKEN"],docs:"https://docs.strapi.io",description:"Open-source self-hosted CMS"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function $n(e){return Bt.find(t=>t.id===e)}var lp=Bt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Yn(e,t,o="global"){let n=$n(t);if(!n)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${Bt.map(s=>s.id).join(", ")}`);let r=bs.join(e,"apps","studio");if(n.id==="none"){X(e,"sanity"),Kt.existsSync(r)&&Kt.rmSync(r,{recursive:!0,force:!0});return}n.id!=="sanity"&&(X(e,"sanity"),Kt.existsSync(r)&&Kt.rmSync(r,{recursive:!0,force:!0})),n.envVars.length>0&&te(e,{category:"CMS",name:n.name,envVars:n.envVars,docs:n.docs}),ne(e,"CMS_PROVIDER",n.id)}import T from"fs";import N from"path";var Ps=N.join("apps","web"),rn=N.join("src","components","compliance"),vt=N.join("src","app","[locale]");function oe(e){return N.join(e,Ps)}function As(e){T.mkdirSync(e,{recursive:!0})}function z(e,t){As(N.dirname(e)),T.writeFileSync(e,t,"utf8")}function sn(e,t){let o=N.join(e,".env.example");if(T.existsSync(o)){if(T.readFileSync(o,"utf8").includes(t.split(`
545
545
  `)[0]??""))return;T.appendFileSync(o,`
546
546
  `+t+`
547
547
  `)}else T.writeFileSync(o,t+`
548
548
  `)}var _t=`> **TEMPLATE \u2014 NOT LEGAL ADVICE.** This document is a boilerplate scaffold only.
549
549
  > Consult a qualified lawyer in every jurisdiction you operate in before publishing.
550
- > \u672C\u6587\u6863\u4E3A\u6A21\u677F\u811A\u624B\u67B6\uFF0C\u4E0D\u6784\u6210\u6CD5\u5F8B\u610F\u89C1\u3002\u53D1\u5E03\u524D\u8BF7\u54A8\u8BE2\u76F8\u5173\u53F8\u6CD5\u8F96\u533A\u7684\u5408\u683C\u5F8B\u5E08\u3002`,Es=`import Link from "next/link";
550
+ > \u672C\u6587\u6863\u4E3A\u6A21\u677F\u811A\u624B\u67B6\uFF0C\u4E0D\u6784\u6210\u6CD5\u5F8B\u610F\u89C1\u3002\u53D1\u5E03\u524D\u8BF7\u54A8\u8BE2\u76F8\u5173\u53F8\u6CD5\u8F96\u533A\u7684\u5408\u683C\u5F8B\u5E08\u3002`,Cs=`import Link from "next/link";
551
551
  import { IcpFooter } from "@/components/compliance/IcpFooter";
552
552
  import { PublicSecurityFooter } from "@/components/compliance/PublicSecurityFooter";
553
553
 
@@ -598,7 +598,7 @@ export function Footer({ region = "global" }: FooterProps) {
598
598
  </footer>
599
599
  );
600
600
  }
601
- `,vs=`export function IcpFooter() {
601
+ `,Is=`export function IcpFooter() {
602
602
  const icp = process.env.NEXT_PUBLIC_ICP_BEIAN;
603
603
  if (!icp) return null;
604
604
  return (
@@ -612,7 +612,7 @@ export function Footer({ region = "global" }: FooterProps) {
612
612
  </a>
613
613
  );
614
614
  }
615
- `,_s=`export function PublicSecurityFooter() {
615
+ `,ws=`export function PublicSecurityFooter() {
616
616
  const psb = process.env.NEXT_PUBLIC_PSB_BEIAN;
617
617
  const psbCode = process.env.NEXT_PUBLIC_PSB_CODE;
618
618
  if (!psb) return null;
@@ -629,7 +629,7 @@ export function Footer({ region = "global" }: FooterProps) {
629
629
  </a>
630
630
  );
631
631
  }
632
- `,bs=`"use client";
632
+ `,Rs=`"use client";
633
633
 
634
634
  import { useCallback, useEffect, useState } from "react";
635
635
 
@@ -856,7 +856,7 @@ function CategoryRow({ id, title, description, checked, disabled, onChange }: Ca
856
856
  </label>
857
857
  );
858
858
  }
859
- `,Ps=`interface AigcDisclaimerProps {
859
+ `,ks=`interface AigcDisclaimerProps {
860
860
  className?: string;
861
861
  }
862
862
 
@@ -876,7 +876,7 @@ export function AigcDisclaimer({ className }: AigcDisclaimerProps) {
876
876
  </div>
877
877
  );
878
878
  }
879
- `,As=`---
879
+ `,xs=`---
880
880
  title: Privacy Policy / \u9690\u79C1\u653F\u7B56
881
881
  description: How {{COMPANY_NAME}} collects, uses, shares, and protects personal information.
882
882
  lastUpdated: 2026-01-01
@@ -1021,7 +1021,7 @@ or in-app notification before the change takes effect.
1021
1021
  **Data Controller / \u6570\u636E\u63A7\u5236\u8005:** {{COMPANY_NAME}}
1022
1022
  **Address / \u5730\u5740:** {{COMPANY_ADDRESS}}
1023
1023
  **Email / \u90AE\u7BB1:** {{COMPANY_CONTACT_EMAIL}}
1024
- `,Cs=`---
1024
+ `,Ns=`---
1025
1025
  title: Terms of Service / \u670D\u52A1\u6761\u6B3E
1026
1026
  description: Terms governing your use of {{COMPANY_NAME}}.
1027
1027
  lastUpdated: 2026-01-01
@@ -1140,7 +1140,7 @@ conflict-of-laws principles. Disputes shall be resolved in the competent courts
1140
1140
  ## 11. Contact / \u8054\u7CFB\u65B9\u5F0F
1141
1141
 
1142
1142
  {{COMPANY_NAME}} \xB7 {{COMPANY_ADDRESS}} \xB7 {{COMPANY_CONTACT_EMAIL}}
1143
- `,Is=`---
1143
+ `,Ts=`---
1144
1144
  title: AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
1145
1145
  description: Disclosure required by \u7F51\u4FE1\u529E\u300A\u751F\u6210\u5F0F\u4EBA\u5DE5\u667A\u80FD\u670D\u52A1\u7BA1\u7406\u6682\u884C\u529E\u6CD5\u300B
1146
1146
  lastUpdated: 2026-01-01
@@ -1222,7 +1222,7 @@ human professional.
1222
1222
 
1223
1223
  AI \u8F93\u51FA\u53EF\u80FD\u4E0D\u51C6\u786E\u3001\u5B58\u5728\u504F\u89C1\u6216\u8FC7\u65F6\u3002**\u8BF7\u52FF**\u5728\u672A\u7ECF\u5408\u683C\u4E13\u4E1A\u4EBA\u58EB\u72EC\u7ACB\u6838\u5B9E\u7684\u60C5\u51B5\u4E0B\uFF0C\u5C06 AI \u8F93\u51FA
1224
1224
  \u7528\u4E8E\u533B\u7597\u3001\u6CD5\u5F8B\u3001\u91D1\u878D\u6216\u5B89\u5168\u6538\u5173\u7684\u51B3\u7B56\u3002
1225
- `,ws=`---
1225
+ `,Os=`---
1226
1226
  title: Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
1227
1227
  description: Notice of cross-border transfer of personal information, per PIPL.
1228
1228
  lastUpdated: 2026-01-01
@@ -1287,7 +1287,7 @@ Refusal may limit your ability to use features that rely on overseas services.
1287
1287
  - \u4F20\u8F93\u4E2D\u52A0\u5BC6 (TLS 1.2+) \u53CA\u9759\u6001\u52A0\u5BC6 (AES-256)\u3002
1288
1288
  - \u5408\u540C\u6761\u6B3E\u8981\u6C42\u5883\u5916\u63A5\u6536\u65B9\u63D0\u4F9B\u7B49\u540C\u4E8E PIPL \u7684\u4FDD\u62A4\u3002
1289
1289
  - \u8BBF\u95EE\u63A7\u5236\u3001\u5BA1\u8BA1\u65E5\u5FD7\u548C\u8FDD\u89C4\u901A\u77E5\u7A0B\u5E8F\u3002
1290
- `,Rs=`---
1290
+ `,Ls=`---
1291
1291
  title: Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
1292
1292
  description: Itemized list of personal information collected, per PIPL Article 17.
1293
1293
  lastUpdated: 2026-01-01
@@ -1329,26 +1329,26 @@ To exercise your rights (access, rectify, delete, export, withdraw consent), con
1329
1329
  **{{COMPANY_CONTACT_EMAIL}}**.
1330
1330
 
1331
1331
  \u5982\u9700\u884C\u4F7F\u60A8\u7684\u6743\u5229\uFF08\u8BBF\u95EE\u3001\u66F4\u6B63\u3001\u5220\u9664\u3001\u5BFC\u51FA\u3001\u64A4\u56DE\u540C\u610F\uFF09\uFF0C\u8BF7\u8054\u7CFB **{{COMPANY_CONTACT_EMAIL}}**\u3002
1332
- `;async function ks(e,t){let o=oe(e);if(!T.existsSync(o))return;let n=N.join(o,"src","components","compliance","Footer.tsx");z(n,Es);let r=N.join(o,"src","components","compliance","README.md");z(r,["# Compliance Components","",`Auto-generated by \`create-sailor\` for region: \`${t}\`.`,"","## Mounting the Footer","","```tsx",'import { Footer } from "@/components/compliance/Footer";','import { CookieBanner } from "@/components/compliance/CookieBanner";',"","export default function RootLayout({ children }) {"," return ("," <html>"," <body>"," {children}",` <Footer region="${t}" />`," <CookieBanner />"," </body>"," </html>"," );","}","```","","## Placeholders","","Policy MDX files contain `{{COMPANY_NAME}}`, `{{COMPANY_ADDRESS}}`,","`{{COMPANY_CONTACT_EMAIL}}`, `{{GOVERNING_JURISDICTION}}`, and","`{{AIGC_ALGORITHM_FILING_NUMBER}}`. These are filled by the `brand-apply` step.",""].join(`
1333
- `))}async function xs(e,t){let o=oe(e);if(!T.existsSync(o))return;let n=N.join(o,"src","components","compliance","CookieBanner.tsx");z(n,bs)}async function Ns(e,t){let o=oe(e);if(!T.existsSync(o))return;let n=N.join(o,vt,"privacy","page.mdx");z(n,As)}async function Ts(e,t){let o=oe(e);if(!T.existsSync(o))return;let n=N.join(o,vt,"terms","page.mdx");z(n,Cs)}async function Os(e){let t=oe(e);if(!T.existsSync(t))return;let o=N.join(t,on,"IcpFooter.tsx");z(o,vs),rn(e,["# Chinese ICP filing (\u5DE5\u4FE1\u90E8 ICP \u5907\u6848) \u2014 required to legally host a","# public-facing site from mainland China. Apply at https://beian.miit.gov.cn/",'NEXT_PUBLIC_ICP_BEIAN="" # \u5982 \u82CFICP\u59072024XXXXXX\u53F7'].join(`
1334
- `))}async function Ls(e){let t=oe(e);if(!T.existsSync(t))return;let o=N.join(t,on,"PublicSecurityFooter.tsx");z(o,_s),rn(e,["# Chinese Public Security Bureau filing (\u516C\u5B89\u8054\u7F51\u5907\u6848)","# Required in addition to ICP. Apply at http://www.beian.gov.cn/",'NEXT_PUBLIC_PSB_BEIAN="" # \u5982 \u82CF\u516C\u7F51\u5B89\u5907 32011402XXXXXX\u53F7','NEXT_PUBLIC_PSB_CODE="" # 14-digit record code'].join(`
1335
- `))}async function Us(e){let t=oe(e);if(!T.existsSync(t))return;let o=N.join(t,on,"AigcDisclaimer.tsx");z(o,Ps),rn(e,["# Generative AI algorithm filing (\u7B97\u6CD5\u5907\u6848\u53F7) \u2014 required by","# \u7F51\u4FE1\u529E\u300A\u751F\u6210\u5F0F\u4EBA\u5DE5\u667A\u80FD\u670D\u52A1\u7BA1\u7406\u6682\u884C\u529E\u6CD5\u300Bfor services offered in China.",'NEXT_PUBLIC_AIGC_FILING_NUMBER="" # e.g. \u7F51\u4FE1\u7B97\u5907XXXXXXXX\u53F7'].join(`
1336
- `))}async function Ms(e){let t=oe(e);if(!T.existsSync(t))return;let o=N.join(t,vt,"aigc-disclosure","page.mdx");z(o,Is)}async function Ds(e){let t=oe(e);if(!T.existsSync(t))return;let o=N.join(t,vt,"cross-border-data","page.mdx");z(o,ws)}async function Fs(e){let t=oe(e);if(!T.existsSync(t))return;let o=N.join(t,vt,"pii-collection","page.mdx");z(o,Rs)}async function Yn(e,t){try{await ks(e,t),await xs(e,t),await Ns(e,t),await Ts(e,t),(t==="cn"||t==="hybrid")&&(await Os(e),await Ls(e),await Us(e),await Ms(e),await Ds(e),await Fs(e))}catch(o){throw console.error("applyComplianceTemplates failed:",o),new Error(`Failed to apply compliance templates for region "${t}". Check that ${e} is writable.`)}}import js from"fs";import Vs from"path";async function qn(e,t){let o=Vs.join(e,"nebutra.config.json");js.writeFileSync(o,JSON.stringify(t,null,2)+`
1337
- `)}import w from"fs";import ke from"path";var sn=[{id:"local",name:"Local / Self-hosted Docker",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres:postgres@localhost:5432/$PROJECT",comment:"Local Postgres via docker-compose (pnpm infra:up)"}],docs:"https://www.postgresql.org/docs/",description:"Docker on localhost. You operate it.",tier:"self-hosted"},{id:"supabase",name:"Supabase",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:6543/postgres?pgbouncer=true",comment:"Supabase pooler \u2014 use for runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:5432/postgres",comment:"Supabase direct \u2014 use for Prisma migrations"},{name:"NEXT_PUBLIC_SUPABASE_URL",placeholder:"https://<project>.supabase.co"},{name:"NEXT_PUBLIC_SUPABASE_ANON_KEY",placeholder:""},{name:"SUPABASE_SERVICE_ROLE_KEY",placeholder:""}],docs:"https://supabase.com/docs",description:"Managed Postgres + auth/storage/realtime/edge-functions.",tier:"managed"},{id:"neon",name:"Neon",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>-pooler.<region>.neon.tech/<db>?sslmode=require",comment:"Neon pooled \u2014 runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>.<region>.neon.tech/<db>?sslmode=require",comment:"Neon direct (no -pooler) \u2014 migrations"}],docs:"https://neon.tech/docs",description:"Serverless Postgres with branching and scale-to-zero.",tier:"managed"},{id:"vercel-postgres",name:"Vercel Postgres",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"$POSTGRES_PRISMA_URL",comment:"Vercel Marketplace injects POSTGRES_PRISMA_URL automatically"},{name:"DIRECT_URL",placeholder:"$POSTGRES_URL_NON_POOLING",comment:"Vercel Marketplace injects POSTGRES_URL_NON_POOLING automatically"}],docs:"https://vercel.com/docs/storage/vercel-postgres",description:"Neon-backed, auto-provisioned via Vercel Marketplace.",tier:"managed"},{id:"planetscale",name:"PlanetScale",region:"global",supportedEngines:["mysql"],forcedEngine:"mysql",prismaDatasourceExtras:['relationMode = "prisma"'],envVars:[{name:"DATABASE_URL",placeholder:"mysql://<user>:<pass>@<host>.psdb.cloud/<db>?sslaccept=strict",comment:'PlanetScale: relationMode = "prisma" (no FK support server-side)'}],docs:"https://planetscale.com/docs",description:"Managed MySQL with branching. No foreign keys.",tier:"managed"},{id:"railway",name:"Railway",region:"global",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"$DATABASE_URL",comment:"Railway service env var; injected when you link a Postgres service"}],docs:"https://docs.railway.app/databases/postgresql",description:"Generalist managed infra; standard TCP Postgres/MySQL.",tier:"managed"},{id:"aliyun-rds",name:"Aliyun RDS",region:"cn",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@<rds-instance>.rds.aliyuncs.com:5432/<db>",comment:"Aliyun RDS Postgres \u2014 internal VPC endpoint recommended"}],docs:"https://www.alibabacloud.com/help/en/rds",description:"Aliyun RDS \u2014 China compliance + intranet routing.",tier:"managed"},{id:"tencent-cdb",name:"Tencent CloudDB (CDB)",region:"cn",supportedEngines:["mysql","postgresql"],envVars:[{name:"DATABASE_URL",placeholder:"mysql://<user>:<pwd>@<cdb-instance>.tencentcdb.com:3306/<db>",comment:"Tencent CloudDB \u2014 VPC endpoint recommended"}],docs:"https://intl.cloud.tencent.com/document/product/236",description:"Tencent CloudDB \u2014 China compliance.",tier:"managed"},{id:"none",name:"None",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[],docs:"",description:"Skip database scaffolding.",tier:"self-hosted"}];function Kt(e){return sn.find(t=>t.id===e)}function Gn(e){return e==="cn"||e==="hybrid"?"local":"supabase"}function Bs(e){w.existsSync(e)&&w.rmSync(e,{recursive:!0,force:!0})}function Hn(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function Ks(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function Wn(e){let t=e.replace(/^\s*extensions\s*=\s*\[[^\]]*\]\s*\n/gm,"");return t=t.replace(/previewFeatures\s*=\s*\[\s*"postgresqlExtensions"\s*\]\s*\n/g,""),t}function $s(e,t){let o=ke.join(e,".env.example");w.existsSync(o)?w.appendFileSync(o,`
1338
- `+t):w.writeFileSync(o,t)}async function Xn(e,t,o){let n=ke.join(e,"packages","platform","db");if(t==="none"){Bs(n);return}let r=ke.join(n,"prisma","schema.prisma"),s;if(t==="postgresql"?s=`postgresql://postgres:postgres@localhost:5432/${o}`:t==="mysql"?s=`mysql://root:root@localhost:3306/${o}`:s="file:./dev.db",$s(e,`# Database (${t})
1332
+ `;async function Us(e,t){let o=oe(e);if(!T.existsSync(o))return;let n=N.join(o,"src","components","compliance","Footer.tsx");z(n,Cs);let r=N.join(o,"src","components","compliance","README.md");z(r,["# Compliance Components","",`Auto-generated by \`create-sailor\` for region: \`${t}\`.`,"","## Mounting the Footer","","```tsx",'import { Footer } from "@/components/compliance/Footer";','import { CookieBanner } from "@/components/compliance/CookieBanner";',"","export default function RootLayout({ children }) {"," return ("," <html>"," <body>"," {children}",` <Footer region="${t}" />`," <CookieBanner />"," </body>"," </html>"," );","}","```","","## Placeholders","","Policy MDX files contain `{{COMPANY_NAME}}`, `{{COMPANY_ADDRESS}}`,","`{{COMPANY_CONTACT_EMAIL}}`, `{{GOVERNING_JURISDICTION}}`, and","`{{AIGC_ALGORITHM_FILING_NUMBER}}`. These are filled by the `brand-apply` step.",""].join(`
1333
+ `))}async function Ms(e,t){let o=oe(e);if(!T.existsSync(o))return;let n=N.join(o,"src","components","compliance","CookieBanner.tsx");z(n,Rs)}async function Ds(e,t){let o=oe(e);if(!T.existsSync(o))return;let n=N.join(o,vt,"privacy","page.mdx");z(n,xs)}async function Fs(e,t){let o=oe(e);if(!T.existsSync(o))return;let n=N.join(o,vt,"terms","page.mdx");z(n,Ns)}async function js(e){let t=oe(e);if(!T.existsSync(t))return;let o=N.join(t,rn,"IcpFooter.tsx");z(o,Is),sn(e,["# Chinese ICP filing (\u5DE5\u4FE1\u90E8 ICP \u5907\u6848) \u2014 required to legally host a","# public-facing site from mainland China. Apply at https://beian.miit.gov.cn/",'NEXT_PUBLIC_ICP_BEIAN="" # \u5982 \u82CFICP\u59072024XXXXXX\u53F7'].join(`
1334
+ `))}async function Vs(e){let t=oe(e);if(!T.existsSync(t))return;let o=N.join(t,rn,"PublicSecurityFooter.tsx");z(o,ws),sn(e,["# Chinese Public Security Bureau filing (\u516C\u5B89\u8054\u7F51\u5907\u6848)","# Required in addition to ICP. Apply at http://www.beian.gov.cn/",'NEXT_PUBLIC_PSB_BEIAN="" # \u5982 \u82CF\u516C\u7F51\u5B89\u5907 32011402XXXXXX\u53F7','NEXT_PUBLIC_PSB_CODE="" # 14-digit record code'].join(`
1335
+ `))}async function Bs(e){let t=oe(e);if(!T.existsSync(t))return;let o=N.join(t,rn,"AigcDisclaimer.tsx");z(o,ks),sn(e,["# Generative AI algorithm filing (\u7B97\u6CD5\u5907\u6848\u53F7) \u2014 required by","# \u7F51\u4FE1\u529E\u300A\u751F\u6210\u5F0F\u4EBA\u5DE5\u667A\u80FD\u670D\u52A1\u7BA1\u7406\u6682\u884C\u529E\u6CD5\u300Bfor services offered in China.",'NEXT_PUBLIC_AIGC_FILING_NUMBER="" # e.g. \u7F51\u4FE1\u7B97\u5907XXXXXXXX\u53F7'].join(`
1336
+ `))}async function Ks(e){let t=oe(e);if(!T.existsSync(t))return;let o=N.join(t,vt,"aigc-disclosure","page.mdx");z(o,Ts)}async function $s(e){let t=oe(e);if(!T.existsSync(t))return;let o=N.join(t,vt,"cross-border-data","page.mdx");z(o,Os)}async function Ys(e){let t=oe(e);if(!T.existsSync(t))return;let o=N.join(t,vt,"pii-collection","page.mdx");z(o,Ls)}async function qn(e,t){try{await Us(e,t),await Ms(e,t),await Ds(e,t),await Fs(e,t),(t==="cn"||t==="hybrid")&&(await js(e),await Vs(e),await Bs(e),await Ks(e),await $s(e),await Ys(e))}catch(o){throw console.error("applyComplianceTemplates failed:",o),new Error(`Failed to apply compliance templates for region "${t}". Check that ${e} is writable.`)}}import qs from"fs";import Gs from"path";async function Gn(e,t){let o=Gs.join(e,"nebutra.config.json");qs.writeFileSync(o,JSON.stringify(t,null,2)+`
1337
+ `)}import R from"fs";import ke from"path";var an=[{id:"local",name:"Local / Self-hosted Docker",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres:postgres@localhost:5432/$PROJECT",comment:"Local Postgres via docker-compose (pnpm infra:up)"}],docs:"https://www.postgresql.org/docs/",description:"Docker on localhost. You operate it.",tier:"self-hosted"},{id:"supabase",name:"Supabase",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:6543/postgres?pgbouncer=true",comment:"Supabase pooler \u2014 use for runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:5432/postgres",comment:"Supabase direct \u2014 use for Prisma migrations"},{name:"NEXT_PUBLIC_SUPABASE_URL",placeholder:"https://<project>.supabase.co"},{name:"NEXT_PUBLIC_SUPABASE_ANON_KEY",placeholder:""},{name:"SUPABASE_SERVICE_ROLE_KEY",placeholder:""}],docs:"https://supabase.com/docs",description:"Managed Postgres + auth/storage/realtime/edge-functions.",tier:"managed"},{id:"neon",name:"Neon",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>-pooler.<region>.neon.tech/<db>?sslmode=require",comment:"Neon pooled \u2014 runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>.<region>.neon.tech/<db>?sslmode=require",comment:"Neon direct (no -pooler) \u2014 migrations"}],docs:"https://neon.tech/docs",description:"Serverless Postgres with branching and scale-to-zero.",tier:"managed"},{id:"vercel-postgres",name:"Vercel Postgres",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"$POSTGRES_PRISMA_URL",comment:"Vercel Marketplace injects POSTGRES_PRISMA_URL automatically"},{name:"DIRECT_URL",placeholder:"$POSTGRES_URL_NON_POOLING",comment:"Vercel Marketplace injects POSTGRES_URL_NON_POOLING automatically"}],docs:"https://vercel.com/docs/storage/vercel-postgres",description:"Neon-backed, auto-provisioned via Vercel Marketplace.",tier:"managed"},{id:"planetscale",name:"PlanetScale",region:"global",supportedEngines:["mysql"],forcedEngine:"mysql",prismaDatasourceExtras:['relationMode = "prisma"'],envVars:[{name:"DATABASE_URL",placeholder:"mysql://<user>:<pass>@<host>.psdb.cloud/<db>?sslaccept=strict",comment:'PlanetScale: relationMode = "prisma" (no FK support server-side)'}],docs:"https://planetscale.com/docs",description:"Managed MySQL with branching. No foreign keys.",tier:"managed"},{id:"railway",name:"Railway",region:"global",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"$DATABASE_URL",comment:"Railway service env var; injected when you link a Postgres service"}],docs:"https://docs.railway.app/databases/postgresql",description:"Generalist managed infra; standard TCP Postgres/MySQL.",tier:"managed"},{id:"aliyun-rds",name:"Aliyun RDS",region:"cn",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@<rds-instance>.rds.aliyuncs.com:5432/<db>",comment:"Aliyun RDS Postgres \u2014 internal VPC endpoint recommended"}],docs:"https://www.alibabacloud.com/help/en/rds",description:"Aliyun RDS \u2014 China compliance + intranet routing.",tier:"managed"},{id:"tencent-cdb",name:"Tencent CloudDB (CDB)",region:"cn",supportedEngines:["mysql","postgresql"],envVars:[{name:"DATABASE_URL",placeholder:"mysql://<user>:<pwd>@<cdb-instance>.tencentcdb.com:3306/<db>",comment:"Tencent CloudDB \u2014 VPC endpoint recommended"}],docs:"https://intl.cloud.tencent.com/document/product/236",description:"Tencent CloudDB \u2014 China compliance.",tier:"managed"},{id:"none",name:"None",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[],docs:"",description:"Skip database scaffolding.",tier:"self-hosted"}];function $t(e){return an.find(t=>t.id===e)}function Hn(e){return e==="cn"||e==="hybrid"?"local":"supabase"}function Hs(e){R.existsSync(e)&&R.rmSync(e,{recursive:!0,force:!0})}function Wn(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function Ws(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function Xn(e){let t=e.replace(/^\s*extensions\s*=\s*\[[^\]]*\]\s*\n/gm,"");return t=t.replace(/previewFeatures\s*=\s*\[\s*"postgresqlExtensions"\s*\]\s*\n/g,""),t}function Xs(e,t){let o=ke.join(e,".env.example");R.existsSync(o)?R.appendFileSync(o,`
1338
+ `+t):R.writeFileSync(o,t)}async function zn(e,t,o){let n=ke.join(e,"packages","platform","db");if(t==="none"){Hs(n);return}let r=ke.join(n,"prisma","schema.prisma"),s;if(t==="postgresql"?s=`postgresql://postgres:postgres@localhost:5432/${o}`:t==="mysql"?s=`mysql://root:root@localhost:3306/${o}`:s="file:./dev.db",Xs(e,`# Database (${t})
1339
1339
  DATABASE_URL="${s}"
1340
- `),!w.existsSync(r))return;let i=w.readFileSync(r,"utf8"),c=i;t==="mysql"?(c=Hn(c,"mysql"),c=Wn(c)):t==="sqlite"&&(c=Hn(c,"sqlite"),c=Ks(c),c=Wn(c)),c!==i&&w.writeFileSync(r,c)}function Ys(e){let t=ke.join(e,".env.example");return w.existsSync(t)?w.readFileSync(t,"utf8"):""}function qs(e,t,o,n){let r=ke.join(e,".env.example"),s=Ys(e),i=n?`# ${n}
1340
+ `),!R.existsSync(r))return;let i=R.readFileSync(r,"utf8"),c=i;t==="mysql"?(c=Wn(c,"mysql"),c=Xn(c)):t==="sqlite"&&(c=Wn(c,"sqlite"),c=Ws(c),c=Xn(c)),c!==i&&R.writeFileSync(r,c)}function zs(e){let t=ke.join(e,".env.example");return R.existsSync(t)?R.readFileSync(t,"utf8"):""}function Js(e,t,o,n){let r=ke.join(e,".env.example"),s=zs(e),i=n?`# ${n}
1341
1341
  ${t}="${o}"
1342
1342
  `:`${t}="${o}"
1343
- `,c=new RegExp(`^\\s*${t}\\s*=.*$`,"m");if(c.test(s)){w.writeFileSync(r,s.replace(c,`${t}="${o}"`));return}s?w.appendFileSync(r,`
1344
- ${i}`):w.writeFileSync(r,i)}function Gs(e,t){let o=ke.join(e,"packages","platform","db","prisma","schema.prisma");if(!w.existsSync(o))return;let n=w.readFileSync(o,"utf8"),r=/(datasource\s+db\s*\{[^}]*?)(\n})/;if(!n.match(r))return;let i=t.filter(l=>!n.includes(l.trim()));if(i.length===0)return;let c=i.map(l=>` ${l}`).join(`
1343
+ `,c=new RegExp(`^\\s*${t}\\s*=.*$`,"m");if(c.test(s)){R.writeFileSync(r,s.replace(c,`${t}="${o}"`));return}s?R.appendFileSync(r,`
1344
+ ${i}`):R.writeFileSync(r,i)}function Qs(e,t){let o=ke.join(e,"packages","platform","db","prisma","schema.prisma");if(!R.existsSync(o))return;let n=R.readFileSync(o,"utf8"),r=/(datasource\s+db\s*\{[^}]*?)(\n})/;if(!n.match(r))return;let i=t.filter(l=>!n.includes(l.trim()));if(i.length===0)return;let c=i.map(l=>` ${l}`).join(`
1345
1345
  `),a=n.replace(r,`$1
1346
- ${c}$2`);w.writeFileSync(o,a)}function Hs(e){let t=ke.join(e,"packages","platform","db","prisma","schema.prisma");if(!w.existsSync(t))return;let o=w.readFileSync(t,"utf8");if(/directUrl\s*=\s*env\(/.test(o))return;let n=/(datasource\s+db\s*\{[\s\S]*?url\s*=\s*env\(\s*"DATABASE_URL"\s*\)[^\n]*\n)/;n.test(o)&&w.writeFileSync(t,o.replace(n,`$1 directUrl = env("DIRECT_URL")
1347
- `))}async function zn(e,t,o){if(!(t.id==="none"||t.id==="local")){for(let n of t.envVars){let r=n.placeholder.replace(/\$PROJECT/g,o);qs(e,n.name,r,n.comment)}t.prismaDatasourceExtras&&t.prismaDatasourceExtras.length>0&&Gs(e,t.prismaDatasourceExtras),t.keepDirectUrl&&Hs(e)}}import at from"fs";import K from"path";import{fileURLToPath as Ws}from"url";var Xs=Ws(import.meta.url),Jn=K.dirname(Xs);function zs(){let e=[K.join(Jn,"..","templates","deploy"),K.join(Jn,"..","..","templates","deploy")];for(let t of e)if(at.existsSync(t))return t;return e[0]}async function Qn(e,t){if(t==="none")return;let o=zs();t==="vercel"?await at.promises.copyFile(K.join(o,"vercel.json"),K.join(e,"vercel.json")):t==="railway"?await at.promises.copyFile(K.join(o,"railway.toml"),K.join(e,"railway.toml")):t==="cloudflare"?await at.promises.copyFile(K.join(o,"wrangler.toml"),K.join(e,"wrangler.toml")):t==="selfhost"&&(await at.promises.copyFile(K.join(o,"docker-compose.yml"),K.join(e,"docker-compose.yml")),await at.promises.copyFile(K.join(o,"Dockerfile.web"),K.join(e,"Dockerfile.web")))}import ge from"fs";import xe from"path";import{fileURLToPath as Js}from"url";var Qs=Js(import.meta.url),Zn=xe.dirname(Qs),Zs=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,eo=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function ei(e){let t=[xe.join(Zn,"..","templates","docs",e),xe.join(Zn,"..","..","templates","docs",e)];for(let o of t)if(ge.existsSync(o))return o;return t[0]}async function to(e,t){if(t.framework==="none")return;if(!eo.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${eo.join(", ")}, none.`);let o=ei(t.framework),n=xe.join(e,"apps","docs");if(!ge.existsSync(o))throw new Error(`Docs template not found: ${o}`);no(o,n),oo(n,{"{PRODUCT_NAME}":t.projectName})}function no(e,t){ge.mkdirSync(t,{recursive:!0});for(let o of ge.readdirSync(e,{withFileTypes:!0})){let n=xe.join(e,o.name),r=xe.join(t,o.name);o.isDirectory()?no(n,r):ge.copyFileSync(n,r)}}function oo(e,t){for(let o of ge.readdirSync(e,{withFileTypes:!0})){let n=xe.join(e,o.name);if(o.isDirectory())oo(n,t);else if(Zs.test(o.name)){let r=ge.readFileSync(n,"utf-8");for(let[s,i]of Object.entries(t))r=r.split(s).join(i);ge.writeFileSync(n,r)}}}import Te from"fs";import Ne from"path";var $t=[{id:"resend",name:"Resend",region:"global",envVars:["RESEND_API_KEY","RESEND_FROM"],docs:"https://resend.com/docs",pkg:"resend",pkgVersion:"^4.0.1"},{id:"postmark",name:"Postmark",region:"global",envVars:["POSTMARK_API_KEY","POSTMARK_FROM"],docs:"https://postmarkapp.com/developer",pkg:"postmark",pkgVersion:"^4.0.5"},{id:"ses",name:"AWS SES",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_SES_REGION","SES_FROM"],docs:"https://docs.aws.amazon.com/ses",pkg:"@aws-sdk/client-sesv2",pkgVersion:"^3.658.0"},{id:"aliyun-dm",name:"\u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001",region:"cn",envVars:["ALIYUN_DM_ACCESS_KEY","ALIYUN_DM_ACCESS_SECRET","ALIYUN_DM_ACCOUNT_NAME","ALIYUN_DM_FROM_ALIAS"],docs:"https://help.aliyun.com/product/29412.html",pkg:"@alicloud/dm20151123",pkgVersion:"^3.0.0"},{id:"tencent-ses",name:"\u817E\u8BAF\u4E91 SES",region:"cn",envVars:["TENCENT_SECRET_ID","TENCENT_SECRET_KEY","TENCENT_SES_FROM_EMAIL"],docs:"https://cloud.tencent.com/document/product/1288",pkg:"tencentcloud-sdk-nodejs-ses",pkgVersion:"^4.0.900"},{id:"netease",name:"\u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1",region:"cn",envVars:["NETEASE_USER","NETEASE_PASS","NETEASE_FROM"],docs:"https://qiye.163.com/help",pkg:"nodemailer",pkgVersion:"^6.9.15"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function ro(e){return $t.find(t=>t.id===e)}var Ip=$t.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Oe="@nebutra/email";function an(e,t){Te.mkdirSync(Ne.dirname(e),{recursive:!0}),Te.writeFileSync(e,t)}function ti(e,t){let o=Ne.join(e,".env.example");Te.existsSync(o)?Te.appendFileSync(o,`
1348
- `+t):Te.writeFileSync(o,t)}function ni(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
1346
+ ${c}$2`);R.writeFileSync(o,a)}function Zs(e){let t=ke.join(e,"packages","platform","db","prisma","schema.prisma");if(!R.existsSync(t))return;let o=R.readFileSync(t,"utf8");if(/directUrl\s*=\s*env\(/.test(o))return;let n=/(datasource\s+db\s*\{[\s\S]*?url\s*=\s*env\(\s*"DATABASE_URL"\s*\)[^\n]*\n)/;n.test(o)&&R.writeFileSync(t,o.replace(n,`$1 directUrl = env("DIRECT_URL")
1347
+ `))}async function Jn(e,t,o){if(!(t.id==="none"||t.id==="local")){for(let n of t.envVars){let r=n.placeholder.replace(/\$PROJECT/g,o);Js(e,n.name,r,n.comment)}t.prismaDatasourceExtras&&t.prismaDatasourceExtras.length>0&&Qs(e,t.prismaDatasourceExtras),t.keepDirectUrl&&Zs(e)}}import at from"fs";import $ from"path";import{fileURLToPath as ei}from"url";var ti=ei(import.meta.url),Qn=$.dirname(ti);function ni(){let e=[$.join(Qn,"..","templates","deploy"),$.join(Qn,"..","..","templates","deploy")];for(let t of e)if(at.existsSync(t))return t;return e[0]}async function Zn(e,t){if(t==="none")return;let o=ni();t==="vercel"?await at.promises.copyFile($.join(o,"vercel.json"),$.join(e,"vercel.json")):t==="railway"?await at.promises.copyFile($.join(o,"railway.toml"),$.join(e,"railway.toml")):t==="cloudflare"?await at.promises.copyFile($.join(o,"wrangler.toml"),$.join(e,"wrangler.toml")):t==="selfhost"&&(await at.promises.copyFile($.join(o,"docker-compose.yml"),$.join(e,"docker-compose.yml")),await at.promises.copyFile($.join(o,"Dockerfile.web"),$.join(e,"Dockerfile.web")))}import ge from"fs";import xe from"path";import{fileURLToPath as oi}from"url";var ri=oi(import.meta.url),eo=xe.dirname(ri),si=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,to=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function ii(e){let t=[xe.join(eo,"..","templates","docs",e),xe.join(eo,"..","..","templates","docs",e)];for(let o of t)if(ge.existsSync(o))return o;return t[0]}async function no(e,t){if(t.framework==="none")return;if(!to.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${to.join(", ")}, none.`);let o=ii(t.framework),n=xe.join(e,"apps","docs");if(!ge.existsSync(o))throw new Error(`Docs template not found: ${o}`);oo(o,n),ro(n,{"{PRODUCT_NAME}":t.projectName})}function oo(e,t){ge.mkdirSync(t,{recursive:!0});for(let o of ge.readdirSync(e,{withFileTypes:!0})){let n=xe.join(e,o.name),r=xe.join(t,o.name);o.isDirectory()?oo(n,r):ge.copyFileSync(n,r)}}function ro(e,t){for(let o of ge.readdirSync(e,{withFileTypes:!0})){let n=xe.join(e,o.name);if(o.isDirectory())ro(n,t);else if(si.test(o.name)){let r=ge.readFileSync(n,"utf-8");for(let[s,i]of Object.entries(t))r=r.split(s).join(i);ge.writeFileSync(n,r)}}}import Te from"fs";import Ne from"path";var Yt=[{id:"resend",name:"Resend",region:"global",envVars:["RESEND_API_KEY","RESEND_FROM"],docs:"https://resend.com/docs",pkg:"resend",pkgVersion:"^4.0.1"},{id:"postmark",name:"Postmark",region:"global",envVars:["POSTMARK_API_KEY","POSTMARK_FROM"],docs:"https://postmarkapp.com/developer",pkg:"postmark",pkgVersion:"^4.0.5"},{id:"ses",name:"AWS SES",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_SES_REGION","SES_FROM"],docs:"https://docs.aws.amazon.com/ses",pkg:"@aws-sdk/client-sesv2",pkgVersion:"^3.658.0"},{id:"aliyun-dm",name:"\u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001",region:"cn",envVars:["ALIYUN_DM_ACCESS_KEY","ALIYUN_DM_ACCESS_SECRET","ALIYUN_DM_ACCOUNT_NAME","ALIYUN_DM_FROM_ALIAS"],docs:"https://help.aliyun.com/product/29412.html",pkg:"@alicloud/dm20151123",pkgVersion:"^3.0.0"},{id:"tencent-ses",name:"\u817E\u8BAF\u4E91 SES",region:"cn",envVars:["TENCENT_SECRET_ID","TENCENT_SECRET_KEY","TENCENT_SES_FROM_EMAIL"],docs:"https://cloud.tencent.com/document/product/1288",pkg:"tencentcloud-sdk-nodejs-ses",pkgVersion:"^4.0.900"},{id:"netease",name:"\u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1",region:"cn",envVars:["NETEASE_USER","NETEASE_PASS","NETEASE_FROM"],docs:"https://qiye.163.com/help",pkg:"nodemailer",pkgVersion:"^6.9.15"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function so(e){return Yt.find(t=>t.id===e)}var Mp=Yt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Oe="@nebutra/email";function cn(e,t){Te.mkdirSync(Ne.dirname(e),{recursive:!0}),Te.writeFileSync(e,t)}function ai(e,t){let o=Ne.join(e,".env.example");Te.existsSync(o)?Te.appendFileSync(o,`
1348
+ `+t):Te.writeFileSync(o,t)}function ci(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
1349
1349
  `);return`${t}
1350
1350
  ${o}
1351
- `}var oi=`/**
1351
+ `}var pi=`/**
1352
1352
  * Public inputs accepted by the \`sendEmail\` wrapper.
1353
1353
  * Keep the surface minimal \u2014 individual providers may accept more, but
1354
1354
  * consumers should code against this shape for portability.
@@ -1368,7 +1368,7 @@ export interface SendEmailResult {
1368
1368
  /** Raw provider response \u2014 useful for debugging, not a stable contract. */
1369
1369
  raw?: unknown;
1370
1370
  }
1371
- `;function ri(){return`/**
1371
+ `;function li(){return`/**
1372
1372
  * @${Oe.slice(1)} \u2014 Resend transactional email wrapper.
1373
1373
  *
1374
1374
  * Docs: https://resend.com/docs
@@ -1407,7 +1407,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1407
1407
  }
1408
1408
 
1409
1409
  export type { SendEmailInput, SendEmailResult } from "./types";
1410
- `}function si(){return`/**
1410
+ `}function di(){return`/**
1411
1411
  * @${Oe.slice(1)} \u2014 Postmark transactional email wrapper.
1412
1412
  *
1413
1413
  * Docs: https://postmarkapp.com/developer
@@ -1445,7 +1445,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1445
1445
  }
1446
1446
 
1447
1447
  export type { SendEmailInput, SendEmailResult } from "./types";
1448
- `}function ii(){return`/**
1448
+ `}function ui(){return`/**
1449
1449
  * @${Oe.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1450
1450
  *
1451
1451
  * Docs: https://docs.aws.amazon.com/ses
@@ -1501,7 +1501,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1501
1501
  }
1502
1502
 
1503
1503
  export type { SendEmailInput, SendEmailResult } from "./types";
1504
- `}function ai(){return`/**
1504
+ `}function mi(){return`/**
1505
1505
  * @${Oe.slice(1)} \u2014 \u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001 (Aliyun DirectMail) wrapper.
1506
1506
  *
1507
1507
  * Docs: https://help.aliyun.com/product/29412.html
@@ -1551,7 +1551,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1551
1551
  }
1552
1552
 
1553
1553
  export type { SendEmailInput, SendEmailResult } from "./types";
1554
- `}function ci(){return`/**
1554
+ `}function gi(){return`/**
1555
1555
  * @${Oe.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1556
1556
  *
1557
1557
  * Docs: https://cloud.tencent.com/document/product/1288
@@ -1599,7 +1599,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1599
1599
  }
1600
1600
 
1601
1601
  export type { SendEmailInput, SendEmailResult } from "./types";
1602
- `}function pi(){return`/**
1602
+ `}function fi(){return`/**
1603
1603
  * @${Oe.slice(1)} \u2014 \u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1 via SMTP (nodemailer).
1604
1604
  *
1605
1605
  * Docs: https://qiye.163.com/help
@@ -1637,31 +1637,32 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1637
1637
  }
1638
1638
 
1639
1639
  export type { SendEmailInput, SendEmailResult } from "./types";
1640
- `}function li(e){switch(e){case"resend":return ri();case"postmark":return si();case"ses":return ii();case"aliyun-dm":return ai();case"tencent-ses":return ci();case"netease":return pi();case"none":return`export {};
1641
- `}}function di(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),e.id==="aliyun-dm"&&(t["@alicloud/openapi-client"]="^0.4.12");let o={name:Oe,version:"0.1.0",private:!0,description:`Transactional email via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(o,null,2)+`
1642
- `}async function so(e,t,o){if(t==="none")return;let n=ro(t);if(!n)throw new Error(`Unknown email provider "${t}". Valid ids: ${$t.map(i=>i.id).join(", ")}`);let r=Ne.join(e,"packages","email"),s=Ne.join(r,"src");Te.existsSync(s)&&Te.rmSync(s,{recursive:!0,force:!0}),an(Ne.join(r,"package.json"),di(n)),an(Ne.join(s,"types.ts"),oi),an(Ne.join(s,"index.ts"),li(n.id)),ti(e,ni(n))}import Yt from"fs";import io from"path";async function ao(e,t){let o=`# Automatically injected by create-sailor
1640
+ `}function yi(e){switch(e){case"resend":return li();case"postmark":return di();case"ses":return ui();case"aliyun-dm":return mi();case"tencent-ses":return gi();case"netease":return fi();case"none":return`export {};
1641
+ `}}function Si(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),e.id==="aliyun-dm"&&(t["@alicloud/openapi-client"]="^0.4.12");let o={name:Oe,version:"0.1.0",private:!0,description:`Transactional email via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(o,null,2)+`
1642
+ `}async function io(e,t,o){if(t==="none")return;let n=so(t);if(!n)throw new Error(`Unknown email provider "${t}". Valid ids: ${Yt.map(i=>i.id).join(", ")}`);let r=Ne.join(e,"packages","email"),s=Ne.join(r,"src");Te.existsSync(s)&&Te.rmSync(s,{recursive:!0,force:!0}),cn(Ne.join(r,"package.json"),Si(n)),cn(Ne.join(s,"types.ts"),pi),cn(Ne.join(s,"index.ts"),yi(n.id)),ai(e,ci(n))}import qt from"fs";import ao from"path";async function co(e,t){let o=`# Automatically injected by create-sailor
1643
1643
  DATABASE_URL="${String(t.databaseUrl)}"
1644
1644
 
1645
1645
  NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="${String(t.clerkPublishable)}"
1646
1646
  CLERK_SECRET_KEY="${String(t.clerkSecret)}"
1647
1647
 
1648
1648
  NEXT_PUBLIC_SITE_URL="http://localhost:3000"
1649
- `,n=io.join(e,".env"),r=io.join(e,".env.local");!Yt.existsSync(n)&&!Yt.existsSync(r)?Yt.writeFileSync(r,o):Yt.appendFileSync(r,`
1650
- `+o)}import po from"crypto";import bt from"fs";import co from"path";function Le(e){return po.randomBytes(e).toString("base64").replace(/=+$/,"")}function ui(e){return po.randomBytes(e).toString("hex")}function mi(){return{AUTH_SECRET:Le(32),NEXTAUTH_SECRET:Le(32),BETTER_AUTH_SECRET:Le(32),JWT_SECRET:Le(32),WEBHOOK_SECRET:ui(16),ENCRYPTION_KEY:Le(32),API_SECRET_KEY:Le(32),SESSION_SECRET:Le(32)}}function gi(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function fi(e,t,o){let n=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=gi(o);return e.replace(n,`${t}="${r}"`)}async function lo(e){let t=co.join(e,".env.example"),o=co.join(e,".env.local");if(!bt.existsSync(t))return null;try{let n=bt.readFileSync(t,"utf8"),r=mi(),i=bt.existsSync(o)?bt.readFileSync(o,"utf8"):n;for(let c of Object.keys(r))i=fi(i,c,r[c]);return bt.writeFileSync(o,i),r}catch(n){let r=n instanceof Error?n.message:String(n);throw console.error(`[create-sailor] Failed to generate env secrets: ${r}`),new Error(`Unable to write .env.local: ${r}`)}}var qt=[{id:"vercel-flags",name:"Vercel Flags SDK",region:"global",envVars:["FLAGS_SECRET"],docs:"https://vercel.com/docs/workflow-collaboration/feature-flags",description:"Native Vercel feature flags"},{id:"growthbook",name:"GrowthBook",region:"both",envVars:["GROWTHBOOK_API_HOST","GROWTHBOOK_CLIENT_KEY","GROWTHBOOK_DECRYPTION_KEY"],docs:"https://docs.growthbook.io",description:"Open-source A/B testing + flags"},{id:"configcat",name:"ConfigCat",region:"global",envVars:["CONFIGCAT_SDK_KEY"],docs:"https://configcat.com/docs/",description:"Feature flag & config management"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function uo(e){return qt.find(t=>t.id===e)}var jp=qt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function mo(e,t,o="global"){let n=uo(t);if(!n)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${qt.map(r=>r.id).join(", ")}`);if(n.id==="none"){X(e,"feature-flags");return}n.envVars.length>0&&te(e,{category:"Feature Flags",name:n.name,envVars:n.envVars,docs:n.docs}),ne(e,"FEATURE_FLAGS_PROVIDER",n.id)}import{execFileSync as yo}from"child_process";import M from"fs";import yi from"os";import fe from"path";import Si from"ignore";var hi={mirror:{repo:process.env.SAILOR_TEMPLATE_REPO||"Nebutra/Sailor-Template",ref:process.env.SAILOR_TEMPLATE_REF||"main",applyIgnore:!1,allowMutableFallback:process.env.SAILOR_TEMPLATE_ALLOW_MUTABLE_FALLBACK==="1"},main:{repo:"Nebutra/Nebutra-Sailor",ref:"main",applyIgnore:!0,allowMutableFallback:process.env.SAILOR_TEMPLATE_ALLOW_MUTABLE_FALLBACK==="1"}};function Ei(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function vi(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function So(e){return/^[0-9a-f]{7,40}$/i.test(e)}function _i(e,t){let o=`https://github.com/${e}.git`,n=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of n)try{let s=yo("git",["ls-remote",o,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!s)continue;let[i]=s.split(/\s+/);if(So(i))return i}catch{}return null}async function bi(e,t){if(So(t))return t;let o=await fetch(`https://api.github.com/repos/${e}/commits/${encodeURIComponent(t)}`,{headers:{Accept:"application/vnd.github+json","User-Agent":"create-sailor"}});if(!o.ok){let r=_i(e,t);if(r)return r;throw new Error(`Failed to resolve ${e}@${t} (GitHub API ${o.status})`)}let n=await o.json();if(typeof n.sha!="string"||n.sha.length===0)throw new Error(`GitHub API did not return a commit SHA for ${e}@${t}`);return n.sha}function ho(e,t,o){let n=M.readdirSync(t,{withFileTypes:!0});for(let r of n){if(r.name==="node_modules"||r.name===".git")continue;let s=fe.join(t,r.name),i=fe.relative(e,s).split(fe.sep).join("/");r.isDirectory()?(o.push(i+"/"),ho(e,s,o)):o.push(i)}}function Pi(e){let t=fe.join(e,".templateignore");if(!M.existsSync(t))return;let o=M.readFileSync(t,"utf8"),n=Si().add(o),r=[];ho(e,e,r);let s=r.map(a=>a.endsWith("/")?a.slice(0,-1):a),i=new Set(n.filter(s)),c=s.filter(a=>!i.has(a)).sort((a,l)=>l.split("/").length-a.split("/").length);for(let a of c){let l=fe.join(e,a);try{M.existsSync(l)&&M.rmSync(l,{recursive:!0,force:!0})}catch{}}try{M.existsSync(t)&&M.rmSync(t,{force:!0})}catch{}}async function go(e,t){let o=await fetch(e,{headers:{Accept:"application/octet-stream","User-Agent":"create-sailor"}});if(!o.ok)throw new Error(`Failed to download archive (${o.status})`);let n=Buffer.from(await o.arrayBuffer());if(n.byteLength<1024)throw new Error(`Downloaded archive is unexpectedly small (${n.byteLength} bytes)`);M.writeFileSync(t,n);let r=M.statSync(t);if(r.size!==n.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${n.byteLength})`);return r.size}function fo(e,t){yo("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function Eo(e){try{let t=M.readdirSync(e);for(let o of t)M.rmSync(fe.join(e,o),{recursive:!0,force:!0})}catch{}}async function Ai(e,t){let o=M.mkdtempSync(fe.join(yi.tmpdir(),"create-sailor-")),n=fe.join(o,"template.tar.gz");try{let r=await bi(e.repo,e.ref);await go(vi(e.repo,r),n),fo(n,t)}catch(r){if(!e.allowMutableFallback)throw r;Eo(t),await go(Ei(e.repo,e.ref),n),fo(n,t)}finally{M.rmSync(o,{recursive:!0,force:!0})}}async function vo(e){M.mkdirSync(e,{recursive:!0});let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],n;for(let r of o){let s=hi[r];try{if(await Ai(s,e),s.applyIgnore)try{Pi(e)}catch(i){throw new Error(`Template cloned, but .templateignore processing failed: ${i instanceof Error?i.message:String(i)}`)}return}catch(i){n=i instanceof Error?i:new Error(String(i)),Eo(e)}}throw new Error(`Failed to download the template from any source. Last error: ${n?.message??"unknown"}
1649
+ `,n=ao.join(e,".env"),r=ao.join(e,".env.local");!qt.existsSync(n)&&!qt.existsSync(r)?qt.writeFileSync(r,o):qt.appendFileSync(r,`
1650
+ `+o)}import lo from"crypto";import bt from"fs";import po from"path";function Le(e){return lo.randomBytes(e).toString("base64").replace(/=+$/,"")}function hi(e){return lo.randomBytes(e).toString("hex")}function Ei(){return{AUTH_SECRET:Le(32),NEXTAUTH_SECRET:Le(32),BETTER_AUTH_SECRET:Le(32),JWT_SECRET:Le(32),WEBHOOK_SECRET:hi(16),ENCRYPTION_KEY:Le(32),API_SECRET_KEY:Le(32),SESSION_SECRET:Le(32)}}function vi(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function _i(e,t,o){let n=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=vi(o);return e.replace(n,`${t}="${r}"`)}async function uo(e){let t=po.join(e,".env.example"),o=po.join(e,".env.local");if(!bt.existsSync(t))return null;try{let n=bt.readFileSync(t,"utf8"),r=Ei(),i=bt.existsSync(o)?bt.readFileSync(o,"utf8"):n;for(let c of Object.keys(r))i=_i(i,c,r[c]);return bt.writeFileSync(o,i),r}catch(n){let r=n instanceof Error?n.message:String(n);throw console.error(`[create-sailor] Failed to generate env secrets: ${r}`),new Error(`Unable to write .env.local: ${r}`)}}var Gt=[{id:"vercel-flags",name:"Vercel Flags SDK",region:"global",envVars:["FLAGS_SECRET"],docs:"https://vercel.com/docs/workflow-collaboration/feature-flags",description:"Native Vercel feature flags"},{id:"growthbook",name:"GrowthBook",region:"both",envVars:["GROWTHBOOK_API_HOST","GROWTHBOOK_CLIENT_KEY","GROWTHBOOK_DECRYPTION_KEY"],docs:"https://docs.growthbook.io",description:"Open-source A/B testing + flags"},{id:"configcat",name:"ConfigCat",region:"global",envVars:["CONFIGCAT_SDK_KEY"],docs:"https://configcat.com/docs/",description:"Feature flag & config management"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function mo(e){return Gt.find(t=>t.id===e)}var Xp=Gt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function go(e,t,o="global"){let n=mo(t);if(!n)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${Gt.map(r=>r.id).join(", ")}`);if(n.id==="none"){X(e,"feature-flags");return}n.envVars.length>0&&te(e,{category:"Feature Flags",name:n.name,envVars:n.envVars,docs:n.docs}),ne(e,"FEATURE_FLAGS_PROVIDER",n.id)}import{existsSync as bi,mkdirSync as fo,writeFileSync as yo}from"fs";import{homedir as So,platform as Pi}from"os";import{join as Pt}from"path";function Ai(){if(Pi()==="win32"){let t=process.env.LOCALAPPDATA||Pt(So(),"AppData","Local");return Pt(t,"nebutra")}let e=process.env.XDG_CONFIG_HOME;return e?Pt(e,"nebutra"):Pt(So(),".config","nebutra")}function Ci(){let e=process.env.NEBUTRA_TELEMETRY;return e==="0"||e==="false"||e==="no"}function ho(){if(!process.stderr.isTTY||!process.stdin.isTTY||process.env.CI)return;let e=Ai(),t=Pt(e,"first-run-acked");try{if(bi(t))return}catch{return}if(Ci()){try{fo(e,{recursive:!0}),yo(t,"")}catch{}return}let o=["[36m\u2139[0m Nebutra collects anonymous usage analytics to improve the scaffolder."," Opt out at any time: export NEBUTRA_TELEMETRY=0"," Privacy policy: https://nebutra.com/legal/cli-analytics",""];try{process.stderr.write(o.join(`
1651
+ `))}catch{}try{fo(e,{recursive:!0}),yo(t,"")}catch{}}import{execFileSync as _o}from"child_process";import D from"fs";import Ii from"os";import fe from"path";import wi from"ignore";var Ri={mirror:{repo:process.env.SAILOR_TEMPLATE_REPO||"Nebutra/Sailor-Template",ref:process.env.SAILOR_TEMPLATE_REF||"main",applyIgnore:!1,allowMutableFallback:process.env.SAILOR_TEMPLATE_ALLOW_MUTABLE_FALLBACK==="1"},main:{repo:"Nebutra/Nebutra-Sailor",ref:"main",applyIgnore:!0,allowMutableFallback:process.env.SAILOR_TEMPLATE_ALLOW_MUTABLE_FALLBACK==="1"}};function ki(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function xi(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function bo(e){return/^[0-9a-f]{7,40}$/i.test(e)}function Ni(e,t){let o=`https://github.com/${e}.git`,n=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of n)try{let s=_o("git",["ls-remote",o,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!s)continue;let[i]=s.split(/\s+/);if(bo(i))return i}catch{}return null}async function Ti(e,t){if(bo(t))return t;let o=await fetch(`https://api.github.com/repos/${e}/commits/${encodeURIComponent(t)}`,{headers:{Accept:"application/vnd.github+json","User-Agent":"create-sailor"}});if(!o.ok){let r=Ni(e,t);if(r)return r;throw new Error(`Failed to resolve ${e}@${t} (GitHub API ${o.status})`)}let n=await o.json();if(typeof n.sha!="string"||n.sha.length===0)throw new Error(`GitHub API did not return a commit SHA for ${e}@${t}`);return n.sha}function Po(e,t,o){let n=D.readdirSync(t,{withFileTypes:!0});for(let r of n){if(r.name==="node_modules"||r.name===".git")continue;let s=fe.join(t,r.name),i=fe.relative(e,s).split(fe.sep).join("/");r.isDirectory()?(o.push(i+"/"),Po(e,s,o)):o.push(i)}}function Oi(e){let t=fe.join(e,".templateignore");if(!D.existsSync(t))return;let o=D.readFileSync(t,"utf8"),n=wi().add(o),r=[];Po(e,e,r);let s=r.map(a=>a.endsWith("/")?a.slice(0,-1):a),i=new Set(n.filter(s)),c=s.filter(a=>!i.has(a)).sort((a,l)=>l.split("/").length-a.split("/").length);for(let a of c){let l=fe.join(e,a);try{D.existsSync(l)&&D.rmSync(l,{recursive:!0,force:!0})}catch{}}try{D.existsSync(t)&&D.rmSync(t,{force:!0})}catch{}}async function Eo(e,t){let o=await fetch(e,{headers:{Accept:"application/octet-stream","User-Agent":"create-sailor"}});if(!o.ok)throw new Error(`Failed to download archive (${o.status})`);let n=Buffer.from(await o.arrayBuffer());if(n.byteLength<1024)throw new Error(`Downloaded archive is unexpectedly small (${n.byteLength} bytes)`);D.writeFileSync(t,n);let r=D.statSync(t);if(r.size!==n.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${n.byteLength})`);return r.size}function vo(e,t){_o("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function Ao(e){try{let t=D.readdirSync(e);for(let o of t)D.rmSync(fe.join(e,o),{recursive:!0,force:!0})}catch{}}async function Li(e,t){let o=D.mkdtempSync(fe.join(Ii.tmpdir(),"create-sailor-")),n=fe.join(o,"template.tar.gz");try{let r=await Ti(e.repo,e.ref);await Eo(xi(e.repo,r),n),vo(n,t)}catch(r){if(!e.allowMutableFallback)throw r;Ao(t),await Eo(ki(e.repo,e.ref),n),vo(n,t)}finally{D.rmSync(o,{recursive:!0,force:!0})}}async function Co(e){D.mkdirSync(e,{recursive:!0});let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],n;for(let r of o){let s=Ri[r];try{if(await Li(s,e),s.applyIgnore)try{Oi(e)}catch(i){throw new Error(`Template cloned, but .templateignore processing failed: ${i instanceof Error?i.message:String(i)}`)}return}catch(i){n=i instanceof Error?i:new Error(String(i)),Ao(e)}}throw new Error(`Failed to download the template from any source. Last error: ${n?.message??"unknown"}
1651
1652
 
1652
1653
  Ensure you have internet access and 'tar' installed.
1653
- You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import{createHmac as Ci,randomBytes as Ii}from"crypto";import J from"fs";import re from"path";import{fileURLToPath as wi}from"url";var Ri=wi(import.meta.url),_o=re.dirname(Ri),bo="scaffold-meta.json",Po=".nebutra",ki="nebutra-sailor:scaffold-marker:v1";function xi(e){if(e)return e;let t=[re.join(_o,"..","templates"),re.join(_o,"..","..","templates")];for(let o of t)if(J.existsSync(o))return o;return t[0]}function Ni(e){let t=`${e.cliVersion}|${e.scaffoldedAt}|${e.projectName}|${e.nonce}`;return Ci("sha256",ki).update(t).digest("hex")}function Ao(e,t){let o=[],n=xi(t.templatesRoot),r=re.join(e,"LICENSE");if(J.existsSync(r)){let C=J.readFileSync(r,"utf-8").slice(0,256);/GNU AFFERO GENERAL PUBLIC LICENSE/i.test(C)&&(J.renameSync(r,re.join(e,"LICENSE-AGPL-REFERENCE.md")),o.push("LICENSE-AGPL-REFERENCE.md (preserved upstream AGPL)"))}let s=re.join(n,"LICENSE-INDEPENDENT.md");if(!J.existsSync(s))throw new Error(`LICENSE-INDEPENDENT.md template missing at ${s}; cannot emit license.`);J.copyFileSync(s,re.join(e,"LICENSE")),o.push("LICENSE");let i=new Date().toISOString(),c=Ii(12).toString("hex"),a=Ni({cliVersion:t.cliVersion,scaffoldedAt:i,projectName:t.projectName,nonce:c}),l={schemaVersion:1,cliVersion:t.cliVersion,scaffoldedAt:i,projectName:t.projectName,nonce:c,signature:a,purpose:"Marks this project as scaffolded by the official `create-sailor` CLI. The Independent Developer License in LICENSE applies as long as this file is present and the signature verifies.",license:{tier:"independent",file:"LICENSE",upgradeUrl:"https://nebutra.com/get-license"}},d=re.join(e,Po);J.mkdirSync(d,{recursive:!0}),J.writeFileSync(re.join(d,bo),`${JSON.stringify(l,null,2)}
1654
- `),o.push(`${Po}/${bo}`);let S=re.join(e,"README.md");if(J.existsSync(S)){let C=J.readFileSync(S,"utf-8");C.includes("Nebutra-Sailor Independent Developer License")||(J.writeFileSync(S,`> **License notice:** scaffolded by \`create-sailor\` under the
1654
+ You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import{createHmac as Mi,randomBytes as Di}from"crypto";import J from"fs";import re from"path";import{fileURLToPath as Fi}from"url";var Ui=[{id:"v1",key:"nebutra-sailor:scaffold-marker:v1"}];function Io(){let e=Ui[0];if(!e)throw new Error("license-signing-keys: registry is empty \u2014 at least one key is required.");return e}var ji=Fi(import.meta.url),wo=re.dirname(ji),Ro="scaffold-meta.json",ko=".nebutra";function Vi(e){if(e)return e;let t=[re.join(wo,"..","templates"),re.join(wo,"..","..","templates")];for(let o of t)if(J.existsSync(o))return o;return t[0]}function Bi(e,t){let o=`${e.cliVersion}|${e.scaffoldedAt}|${e.projectName}|${e.nonce}`;return Mi("sha256",t).update(o).digest("hex")}function xo(e,t){let o=[],n=Vi(t.templatesRoot),r=re.join(e,"LICENSE");if(J.existsSync(r)){let C=J.readFileSync(r,"utf-8").slice(0,256);/GNU AFFERO GENERAL PUBLIC LICENSE/i.test(C)&&(J.renameSync(r,re.join(e,"LICENSE-AGPL-REFERENCE.md")),o.push("LICENSE-AGPL-REFERENCE.md (preserved upstream AGPL)"))}let s=re.join(n,"LICENSE-INDEPENDENT.md");if(!J.existsSync(s))throw new Error(`LICENSE-INDEPENDENT.md template missing at ${s}; cannot emit license.`);J.copyFileSync(s,re.join(e,"LICENSE")),o.push("LICENSE");let i=new Date().toISOString(),c=Di(12).toString("hex"),a=Io(),l=Bi({cliVersion:t.cliVersion,scaffoldedAt:i,projectName:t.projectName,nonce:c},a.key),u={schemaVersion:1,cliVersion:t.cliVersion,scaffoldedAt:i,projectName:t.projectName,nonce:c,signature:l,signingKeyId:a.id,purpose:"Marks this project as scaffolded by the official `create-sailor` CLI. The Independent Developer License in LICENSE applies as long as this file is present and the signature verifies.",license:{tier:"independent",file:"LICENSE",upgradeUrl:"https://nebutra.com/get-license"}},S=re.join(e,ko);J.mkdirSync(S,{recursive:!0}),J.writeFileSync(re.join(S,Ro),`${JSON.stringify(u,null,2)}
1655
+ `),o.push(`${ko}/${Ro}`);let I=re.join(e,"README.md");if(J.existsSync(I)){let C=J.readFileSync(I,"utf-8");C.includes("Nebutra-Sailor Independent Developer License")||(J.writeFileSync(I,`> **License notice:** scaffolded by \`create-sailor\` under the
1655
1656
  > [Nebutra-Sailor Independent Developer License](./LICENSE). Free for
1656
1657
  > individuals/OPC with \u2264 1 FTE and < $1M ARR; upgrade for larger teams at
1657
1658
  > https://nebutra.com/get-license. The upstream repository remains
1658
1659
  > AGPL-3.0 \u2014 see \`LICENSE-AGPL-REFERENCE.md\`.
1659
1660
 
1660
- `+C),o.push("README.md (prepended license notice)"))}return{wrote:o}}import Ue from"fs";import cn from"path";async function Co(e,t){let o=cn.join(e,"packages","mcp");if(t==="off"){Ue.existsSync(o)&&Ue.rmSync(o,{recursive:!0,force:!0});let r=cn.join(e,"packages","cli","src","commands","mcp-server.ts");Ue.existsSync(r)&&Ue.rmSync(r,{force:!0});return}let n=cn.join(e,".env.example");if(Ue.existsSync(n)){let r=Ue.readFileSync(n,"utf-8"),s="# MCP Server (Agent-friendly API)";if(!r.includes(s)){let i=["","# =============================================",s,"# Docs: https://modelcontextprotocol.io","# =============================================","# MCP server exposes your SaaS capabilities to AI agents via MCP protocol.","# Run: pnpm mcp-server (starts stdio server)","# No config required for stdio transport. HTTP transport needs:",'MCP_HTTP_PORT="3100"','MCP_API_KEY=""',""].join(`
1661
- `);Ue.appendFileSync(n,i)}}}import Pt from"fs";import Io from"path";async function wo(e,t,o){let n=Io.join(e,"packages","metering"),r;if(t==="auto"?r=o!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){Pt.existsSync(n)&&Pt.rmSync(n,{recursive:!0,force:!0});return}let s=Io.join(e,".env.example");if(!Pt.existsSync(s))return;let i=Pt.readFileSync(s,"utf-8"),c="# Metering (usage-based billing)";if(!i.includes(c)){let a=["","# =============================================",c,"# Docs: see packages/commerce/metering/README.md","# =============================================","# ClickHouse-based metering pipeline for consumption billing.",'CLICKHOUSE_URL=""','CLICKHOUSE_USER="default"','CLICKHOUSE_PASSWORD=""','CLICKHOUSE_DATABASE="metering"',""].join(`
1662
- `);Pt.appendFileSync(s,a)}}import ce from"fs";import D from"path";var Ro=[{id:"sentry",name:"Sentry",region:"both",envVars:["SENTRY_DSN","NEXT_PUBLIC_SENTRY_DSN"],docs:"https://docs.sentry.io",pkg:"@sentry/nextjs",instrumentationFile:"apps/web/instrumentation.ts"},{id:"datadog",name:"Datadog",region:"global",envVars:["DD_API_KEY","DD_APP_KEY","DD_SITE"],docs:"https://docs.datadoghq.com",pkg:"dd-trace",instrumentationFile:"apps/web/instrumentation.ts"},{id:"bugsnag",name:"Bugsnag",region:"global",envVars:["BUGSNAG_API_KEY","NEXT_PUBLIC_BUGSNAG_API_KEY"],docs:"https://docs.bugsnag.com",pkg:"@bugsnag/js",instrumentationFile:"apps/web/src/lib/monitoring/bugsnag.ts"},{id:"aliyun-arms",name:"\u963F\u91CC\u4E91 ARMS",region:"cn",envVars:["ALIYUN_ARMS_LICENSE_KEY","ALIYUN_ARMS_APP_NAME","NEXT_PUBLIC_ARMS_PID"],docs:"https://help.aliyun.com/product/34364.html",instrumentationFile:"apps/web/src/components/monitoring/ArmsScript.tsx"},{id:"tingyun",name:"\u542C\u4E91 TingYun",region:"cn",envVars:["TINGYUN_LICENSE_KEY","NEXT_PUBLIC_TINGYUN_APP_KEY"],docs:"https://www.tingyun.com/docs",instrumentationFile:"apps/web/src/components/monitoring/TingYunScript.tsx"},{id:"none",name:"None",region:"both",envVars:[],docs:""}],al=Ro.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function ko(e){return Ro.find(t=>t.id===e)}var pn={sentry:{"@sentry/nextjs":"^8.45.0"},datadog:{"dd-trace":"^5.32.0","@datadog/browser-rum":"^5.30.0"},bugsnag:{"@bugsnag/js":"^8.2.0","@bugsnag/plugin-react":"^8.2.0"}};function Ti(e){ce.mkdirSync(e,{recursive:!0})}function ln(e,t){let o=D.join(e,"package.json");if(!ce.existsSync(o))return;let n;try{n=JSON.parse(ce.readFileSync(o,"utf-8"))}catch(c){console.error(`Failed to parse ${o}:`,c);return}let s={...n.dependencies??{}};for(let[c,a]of Object.entries(t))s[c]||(s[c]=a);let i={...n,dependencies:s};ce.writeFileSync(o,JSON.stringify(i,null,2)+`
1663
- `)}function se(e,t){Ti(D.dirname(e)),ce.writeFileSync(e,t)}function At(e,t){let o=D.join(e,".env.example");ce.existsSync(o)?ce.appendFileSync(o,`
1664
- `+t):ce.writeFileSync(o,t)}function Oi(e){let t=`import * as Sentry from "@sentry/nextjs";
1661
+ `+C),o.push("README.md (prepended license notice)"))}return{wrote:o}}import Ue from"fs";import pn from"path";async function No(e,t){let o=pn.join(e,"packages","mcp");if(t==="off"){Ue.existsSync(o)&&Ue.rmSync(o,{recursive:!0,force:!0});let r=pn.join(e,"packages","cli","src","commands","mcp-server.ts");Ue.existsSync(r)&&Ue.rmSync(r,{force:!0});return}let n=pn.join(e,".env.example");if(Ue.existsSync(n)){let r=Ue.readFileSync(n,"utf-8"),s="# MCP Server (Agent-friendly API)";if(!r.includes(s)){let i=["","# =============================================",s,"# Docs: https://modelcontextprotocol.io","# =============================================","# MCP server exposes your SaaS capabilities to AI agents via MCP protocol.","# Run: pnpm mcp-server (starts stdio server)","# No config required for stdio transport. HTTP transport needs:",'MCP_HTTP_PORT="3100"','MCP_API_KEY=""',""].join(`
1662
+ `);Ue.appendFileSync(n,i)}}}import At from"fs";import To from"path";async function Oo(e,t,o){let n=To.join(e,"packages","metering"),r;if(t==="auto"?r=o!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){At.existsSync(n)&&At.rmSync(n,{recursive:!0,force:!0});return}let s=To.join(e,".env.example");if(!At.existsSync(s))return;let i=At.readFileSync(s,"utf-8"),c="# Metering (usage-based billing)";if(!i.includes(c)){let a=["","# =============================================",c,"# Docs: see packages/commerce/metering/README.md","# =============================================","# ClickHouse-based metering pipeline for consumption billing.",'CLICKHOUSE_URL=""','CLICKHOUSE_USER="default"','CLICKHOUSE_PASSWORD=""','CLICKHOUSE_DATABASE="metering"',""].join(`
1663
+ `);At.appendFileSync(s,a)}}import ce from"fs";import F from"path";var Lo=[{id:"sentry",name:"Sentry",region:"both",envVars:["SENTRY_DSN","NEXT_PUBLIC_SENTRY_DSN"],docs:"https://docs.sentry.io",pkg:"@sentry/nextjs",instrumentationFile:"apps/web/instrumentation.ts"},{id:"datadog",name:"Datadog",region:"global",envVars:["DD_API_KEY","DD_APP_KEY","DD_SITE"],docs:"https://docs.datadoghq.com",pkg:"dd-trace",instrumentationFile:"apps/web/instrumentation.ts"},{id:"bugsnag",name:"Bugsnag",region:"global",envVars:["BUGSNAG_API_KEY","NEXT_PUBLIC_BUGSNAG_API_KEY"],docs:"https://docs.bugsnag.com",pkg:"@bugsnag/js",instrumentationFile:"apps/web/src/lib/monitoring/bugsnag.ts"},{id:"aliyun-arms",name:"\u963F\u91CC\u4E91 ARMS",region:"cn",envVars:["ALIYUN_ARMS_LICENSE_KEY","ALIYUN_ARMS_APP_NAME","NEXT_PUBLIC_ARMS_PID"],docs:"https://help.aliyun.com/product/34364.html",instrumentationFile:"apps/web/src/components/monitoring/ArmsScript.tsx"},{id:"tingyun",name:"\u542C\u4E91 TingYun",region:"cn",envVars:["TINGYUN_LICENSE_KEY","NEXT_PUBLIC_TINGYUN_APP_KEY"],docs:"https://www.tingyun.com/docs",instrumentationFile:"apps/web/src/components/monitoring/TingYunScript.tsx"},{id:"none",name:"None",region:"both",envVars:[],docs:""}],Al=Lo.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Uo(e){return Lo.find(t=>t.id===e)}var ln={sentry:{"@sentry/nextjs":"^8.45.0"},datadog:{"dd-trace":"^5.32.0","@datadog/browser-rum":"^5.30.0"},bugsnag:{"@bugsnag/js":"^8.2.0","@bugsnag/plugin-react":"^8.2.0"}};function Ki(e){ce.mkdirSync(e,{recursive:!0})}function dn(e,t){let o=F.join(e,"package.json");if(!ce.existsSync(o))return;let n;try{n=JSON.parse(ce.readFileSync(o,"utf-8"))}catch(c){console.error(`Failed to parse ${o}:`,c);return}let s={...n.dependencies??{}};for(let[c,a]of Object.entries(t))s[c]||(s[c]=a);let i={...n,dependencies:s};ce.writeFileSync(o,JSON.stringify(i,null,2)+`
1664
+ `)}function se(e,t){Ki(F.dirname(e)),ce.writeFileSync(e,t)}function Ct(e,t){let o=F.join(e,".env.example");ce.existsSync(o)?ce.appendFileSync(o,`
1665
+ `+t):ce.writeFileSync(o,t)}function $i(e){let t=`import * as Sentry from "@sentry/nextjs";
1665
1666
 
1666
1667
  Sentry.init({
1667
1668
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
@@ -1704,14 +1705,14 @@ export async function register() {
1704
1705
  }
1705
1706
 
1706
1707
  export { captureRequestError as onRequestError } from "@sentry/nextjs";
1707
- `;se(D.join(e,"sentry.client.config.ts"),t),se(D.join(e,"sentry.server.config.ts"),o),se(D.join(e,"sentry.edge.config.ts"),n),se(D.join(e,"instrumentation.ts"),r)}function Li(){return`# Sentry \u2014 error tracking + performance monitoring
1708
+ `;se(F.join(e,"sentry.client.config.ts"),t),se(F.join(e,"sentry.server.config.ts"),o),se(F.join(e,"sentry.edge.config.ts"),n),se(F.join(e,"instrumentation.ts"),r)}function Yi(){return`# Sentry \u2014 error tracking + performance monitoring
1708
1709
  # Get your DSN from https://sentry.io/settings/projects/<project>/keys/
1709
1710
  SENTRY_DSN=
1710
1711
  NEXT_PUBLIC_SENTRY_DSN=
1711
1712
  SENTRY_ORG=
1712
1713
  SENTRY_PROJECT=
1713
1714
  SENTRY_AUTH_TOKEN=
1714
- `}function Ui(e){let t=`/**
1715
+ `}function qi(e){let t=`/**
1715
1716
  * Next.js instrumentation hook \u2014 wires Datadog APM (dd-trace) into Node runtime.
1716
1717
  * Edge runtime is not supported by dd-trace; only nodejs is initialized.
1717
1718
  */
@@ -1759,7 +1760,7 @@ export function initDatadogRum(): void {
1759
1760
  });
1760
1761
  initialized = true;
1761
1762
  }
1762
- `;se(D.join(e,"instrumentation.ts"),t),se(D.join(e,"src","lib","monitoring","datadog-rum.ts"),o)}function Mi(){return`# Datadog \u2014 APM + RUM
1763
+ `;se(F.join(e,"instrumentation.ts"),t),se(F.join(e,"src","lib","monitoring","datadog-rum.ts"),o)}function Gi(){return`# Datadog \u2014 APM + RUM
1763
1764
  # Server APM (dd-trace)
1764
1765
  DD_API_KEY=
1765
1766
  DD_APP_KEY=
@@ -1774,7 +1775,7 @@ NEXT_PUBLIC_DD_SITE=datadoghq.com
1774
1775
  NEXT_PUBLIC_DD_SERVICE=sailor-web
1775
1776
  NEXT_PUBLIC_DD_ENV=production
1776
1777
  NEXT_PUBLIC_DD_VERSION=
1777
- `}function Di(e){let t=`/**
1778
+ `}function Hi(e){let t=`/**
1778
1779
  * Bugsnag server-side initialization.
1779
1780
  * Import this once at the top of your server entrypoint or a shared init module.
1780
1781
  */
@@ -1823,11 +1824,11 @@ export function getBugsnagErrorBoundary() {
1823
1824
  errorBoundary = plugin.createErrorBoundary(React) as typeof errorBoundary;
1824
1825
  return errorBoundary;
1825
1826
  }
1826
- `;se(D.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),se(D.join(e,"src","lib","monitoring","bugsnag.client.tsx"),o)}function Fi(){return`# Bugsnag \u2014 error tracking
1827
+ `;se(F.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),se(F.join(e,"src","lib","monitoring","bugsnag.client.tsx"),o)}function Wi(){return`# Bugsnag \u2014 error tracking
1827
1828
  BUGSNAG_API_KEY=
1828
1829
  NEXT_PUBLIC_BUGSNAG_API_KEY=
1829
1830
  APP_VERSION=
1830
- `}function ji(e){se(D.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1831
+ `}function Xi(e){se(F.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1831
1832
  /**
1832
1833
  * \u963F\u91CC\u4E91 ARMS (Application Real-time Monitoring Service) browser agent.
1833
1834
  * Injects the official JS agent via next/script.
@@ -1848,11 +1849,11 @@ export function ArmsScript() {
1848
1849
  />
1849
1850
  );
1850
1851
  }
1851
- `)}function Vi(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1852
+ `)}function zi(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1852
1853
  ALIYUN_ARMS_LICENSE_KEY=
1853
1854
  ALIYUN_ARMS_APP_NAME=
1854
1855
  NEXT_PUBLIC_ARMS_PID=
1855
- `}function Bi(e){se(D.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1856
+ `}function Ji(e){se(F.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1856
1857
  /**
1857
1858
  * \u542C\u4E91 Browser Agent (\u524D\u7AEF\u6027\u80FD\u76D1\u63A7).
1858
1859
  * Docs: https://www.tingyun.com/docs
@@ -1870,12 +1871,12 @@ export function TingYunScript() {
1870
1871
  />
1871
1872
  );
1872
1873
  }
1873
- `)}function Ki(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1874
+ `)}function Qi(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1874
1875
  TINGYUN_LICENSE_KEY=
1875
1876
  NEXT_PUBLIC_TINGYUN_APP_KEY=
1876
- `}async function xo(e,t,o="global"){let n=ko(t);if(!n||n.id==="none")return;let r=D.join(e,"apps","web");if(!ce.existsSync(r))return;let s=n.id;try{switch(s){case"sentry":Oi(r),ln(r,pn.sentry),At(e,Li());return;case"datadog":Ui(r),ln(r,pn.datadog),At(e,Mi());return;case"bugsnag":Di(r),ln(r,pn.bugsnag),At(e,Fi());return;case"aliyun-arms":ji(r),At(e,Vi());return;case"tingyun":Bi(r),At(e,Ki());return;default:return}}catch(i){throw console.error(`Failed to apply monitoring selection "${t}":`,i),new Error(`Monitoring scaffold for "${t}" failed \u2014 see stderr for details.`)}}var Gt=[{id:"novu",name:"Novu",region:"both",envVars:["NOVU_API_KEY","NOVU_APPLICATION_IDENTIFIER"],docs:"https://docs.novu.co",description:"Multi-channel notification infrastructure"},{id:"knock",name:"Knock",region:"global",envVars:["KNOCK_API_KEY","KNOCK_SIGNING_KEY","KNOCK_PUBLIC_API_KEY"],docs:"https://docs.knock.app",description:"Product notifications platform"},{id:"custom",name:"Custom (direct dispatchers)",region:"both",envVars:[],docs:"",description:"Use email + sms + push directly"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function No(e){return Gt.find(t=>t.id===e)}var ml=Gt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function To(e,t,o="global"){let n=No(t);if(!n)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${Gt.map(r=>r.id).join(", ")}`);if(n.id==="none"){X(e,"notifications");return}n.envVars.length>0&&te(e,{category:"Notifications",name:n.name,envVars:n.envVars,docs:n.docs}),ne(e,"NOTIFICATIONS_PROVIDER",n.id)}import dn from"fs";import $i from"path";async function Oo(e,t){let o=$i.join(e,"package.json");if(dn.existsSync(o)){let n=dn.readFileSync(o,"utf8"),r=JSON.parse(n);r.name=t,r.version="0.1.0",dn.writeFileSync(o,JSON.stringify(r,null,2)+`
1877
- `)}}import Ht from"fs";import ct from"path";import{fileURLToPath as Yi}from"url";var qi=Yi(import.meta.url),Lo=ct.dirname(qi);function Gi(){let e=[ct.join(Lo,"..","templates","orm","drizzle"),ct.join(Lo,"..","..","templates","orm","drizzle")];for(let t of e)if(Ht.existsSync(t))return t;return null}function Uo(e,t){Ht.mkdirSync(t,{recursive:!0});for(let o of Ht.readdirSync(e,{withFileTypes:!0})){let n=ct.join(e,o.name),r=ct.join(t,o.name);o.isDirectory()?Uo(n,r):Ht.copyFileSync(n,r)}}async function Mo(e,t,o){if(t!=="drizzle")return{applied:!1};if(o!=="postgresql")return{applied:!1,reason:`Drizzle template currently targets Postgres only; --db=${o} keeps Prisma as sole ORM`};let n=Gi();if(!n)return{applied:!1,reason:"Drizzle template directory not found in package \u2014 bundling error"};let r=ct.join(e,"packages","platform","db-drizzle");return Uo(n,r),{applied:!0}}import pe from"fs";import Ct from"path";var Hi=["stripe","lemonsqueezy","chinapay","polar"];function Do(e){pe.existsSync(e)&&pe.rmSync(e,{recursive:!0,force:!0})}function Wi(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function Xi(e,t){let o=Ct.join(e,".env.example");pe.existsSync(o)?pe.appendFileSync(o,`
1878
- `+t):pe.writeFileSync(o,t)}function zi(e){switch(e){case"stripe":return`# Stripe
1877
+ `}async function Mo(e,t,o="global"){let n=Uo(t);if(!n||n.id==="none")return;let r=F.join(e,"apps","web");if(!ce.existsSync(r))return;let s=n.id;try{switch(s){case"sentry":$i(r),dn(r,ln.sentry),Ct(e,Yi());return;case"datadog":qi(r),dn(r,ln.datadog),Ct(e,Gi());return;case"bugsnag":Hi(r),dn(r,ln.bugsnag),Ct(e,Wi());return;case"aliyun-arms":Xi(r),Ct(e,zi());return;case"tingyun":Ji(r),Ct(e,Qi());return;default:return}}catch(i){throw console.error(`Failed to apply monitoring selection "${t}":`,i),new Error(`Monitoring scaffold for "${t}" failed \u2014 see stderr for details.`)}}var Ht=[{id:"novu",name:"Novu",region:"both",envVars:["NOVU_API_KEY","NOVU_APPLICATION_IDENTIFIER"],docs:"https://docs.novu.co",description:"Multi-channel notification infrastructure"},{id:"knock",name:"Knock",region:"global",envVars:["KNOCK_API_KEY","KNOCK_SIGNING_KEY","KNOCK_PUBLIC_API_KEY"],docs:"https://docs.knock.app",description:"Product notifications platform"},{id:"custom",name:"Custom (direct dispatchers)",region:"both",envVars:[],docs:"",description:"Use email + sms + push directly"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Do(e){return Ht.find(t=>t.id===e)}var xl=Ht.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Fo(e,t,o="global"){let n=Do(t);if(!n)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${Ht.map(r=>r.id).join(", ")}`);if(n.id==="none"){X(e,"notifications");return}n.envVars.length>0&&te(e,{category:"Notifications",name:n.name,envVars:n.envVars,docs:n.docs}),ne(e,"NOTIFICATIONS_PROVIDER",n.id)}import un from"fs";import Zi from"path";async function jo(e,t){let o=Zi.join(e,"package.json");if(un.existsSync(o)){let n=un.readFileSync(o,"utf8"),r=JSON.parse(n);r.name=t,r.version="0.1.0",un.writeFileSync(o,JSON.stringify(r,null,2)+`
1878
+ `)}}import Wt from"fs";import ct from"path";import{fileURLToPath as ea}from"url";var ta=ea(import.meta.url),Vo=ct.dirname(ta);function na(){let e=[ct.join(Vo,"..","templates","orm","drizzle"),ct.join(Vo,"..","..","templates","orm","drizzle")];for(let t of e)if(Wt.existsSync(t))return t;return null}function Bo(e,t){Wt.mkdirSync(t,{recursive:!0});for(let o of Wt.readdirSync(e,{withFileTypes:!0})){let n=ct.join(e,o.name),r=ct.join(t,o.name);o.isDirectory()?Bo(n,r):Wt.copyFileSync(n,r)}}async function Ko(e,t,o){if(t!=="drizzle")return{applied:!1};if(o!=="postgresql")return{applied:!1,reason:`Drizzle template currently targets Postgres only; --db=${o} keeps Prisma as sole ORM`};let n=na();if(!n)return{applied:!1,reason:"Drizzle template directory not found in package \u2014 bundling error"};let r=ct.join(e,"packages","platform","db-drizzle");return Bo(n,r),{applied:!0}}import pe from"fs";import It from"path";var oa=["stripe","lemonsqueezy","chinapay","polar"];function $o(e){pe.existsSync(e)&&pe.rmSync(e,{recursive:!0,force:!0})}function ra(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function sa(e,t){let o=It.join(e,".env.example");pe.existsSync(o)?pe.appendFileSync(o,`
1879
+ `+t):pe.writeFileSync(o,t)}function ia(e){switch(e){case"stripe":return`# Stripe
1879
1880
  STRIPE_SECRET_KEY=
1880
1881
  STRIPE_WEBHOOK_SECRET=
1881
1882
  `;case"lemon":return`# Lemon Squeezy
@@ -1890,14 +1891,14 @@ CHINAPAY_WECHAT_ENABLED=true
1890
1891
  CHINAPAY_APP_ID=
1891
1892
  CHINAPAY_APP_SECRET=
1892
1893
  CHINAPAY_ALIPAY_ENABLED=true
1893
- `}}async function Fo(e,t){let o=Ct.join(e,"packages","commerce","billing");if(!pe.existsSync(o))return;if(t==="none"){Do(o);return}let n=Ct.join(o,"src"),r=new Set(Wi(t));for(let i of Hi)r.has(i)||Do(Ct.join(n,i));let s=Ct.join(n,"checkout","types.ts");if(pe.existsSync(s)){let i=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",c=pe.readFileSync(s,"utf8"),a=c.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${i}";`);a!==c&&pe.writeFileSync(s,a)}Xi(e,zi(t))}import ye from"fs";import pt from"path";var Bo=new Set(["siliconflow","volcengine-ark","bailian","moonshot"]),un=/@sailor:([^\s*]+)/;function Ji(e,t){let{providerIds:o,customEndpoint:n}=t;if(e.startsWith("provider:")){let r=e.slice(9);return{marker:e,keep:o.includes(r)}}if(e==="cn-compatible"){let r=o.some(s=>Bo.has(s));return{marker:e,keep:r||!!n}}if(e.startsWith("cn-instance:")){let r=e.slice(12);return{marker:e,keep:o.includes(r)}}return e==="custom-endpoint"?{marker:e,keep:!!n}:e==="registry-entries"?{marker:e,keep:!0}:{marker:e,keep:!0}}function jo(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function Vo(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function Ko(e,t){let o=e.split(`
1894
- `),n=[],r=e.includes("#"),s=0;for(;s<o.length;){let i=o[s],c=i.match(un);if(!c){n.push(i),s++;continue}let{marker:a,keep:l}=Ji(c[1],t);if(a==="registry-entries"){n.push(r?Vo(i):jo(i)),s++;continue}if(l){let d=r?Vo(i):jo(i);d.trim().length>0&&n.push(d);let S=s+1;for(;S<o.length&&o[S].trim()!==""&&!un.test(o[S]);)n.push(o[S]),S++;S<o.length&&o[S].trim()===""&&(n.push(o[S]),S++),s=S}else{let d=s+1;for(;d<o.length&&o[d].trim()!==""&&!un.test(o[d]);)d++;d<o.length&&o[d].trim()===""&&d++,s=d}}return Qi(n.join(`
1895
- `),t)}function Qi(e,t){let{providerIds:o,customEndpoint:n}=t,r=new Set;for(let l of o)["openai","anthropic","google","mistral","xai"].includes(l)&&r.add(l),r.add(l.replace(/-/g,"_")),r.add(l);n&&r.add("custom");let s=/createProviderRegistry\(\{([\s\S]*?)\}\)/,i=e.match(s);if(!i)return e;let a=i[1].split(`
1896
- `).filter(l=>{let d=l.trim();if(d===""||d.startsWith("//"))return!0;let S=d.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return S?r.has(S[1]):!0}).join(`
1897
- `);return e.replace(s,`createProviderRegistry({${a}})`)}function Zi(e,t){let o=pt.join(t,"registry.ts.template"),n=ye.readFileSync(o,"utf-8");return Ko(n,e)}function ea(e,t){let o=pt.join(t,".env.example.template"),n=ye.readFileSync(o,"utf-8");return Ko(n,e)}async function $o(e,t,o){let n=Zi(t,o),r=ea(t,o),s=pt.join(e,"packages/ai/agents/src");await ye.promises.mkdir(s,{recursive:!0}),await ye.promises.writeFile(pt.join(s,"registry.ts"),n),await ye.promises.appendFile(pt.join(e,".env.example"),`
1898
- `+r);let i={ai:"latest"},{providerIds:c,customEndpoint:a}=t;(c.includes("openai")||a||c.some(d=>Bo.has(d)))&&(i["@ai-sdk/openai"]="latest",i["@ai-sdk/openai-compatible"]="latest"),c.includes("anthropic")&&(i["@ai-sdk/anthropic"]="latest"),c.includes("google")&&(i["@ai-sdk/google"]="latest"),c.includes("mistral")&&(i["@ai-sdk/mistral"]="latest"),c.includes("xai")&&(i["@ai-sdk/openai"]="latest");let l=pt.join(e,"package.json");if(ye.existsSync(l)){let d=JSON.parse(await ye.promises.readFile(l,"utf-8"));d.dependencies||(d.dependencies={});for(let[S,C]of Object.entries(i))d.dependencies[S]=C;await ye.promises.writeFile(l,JSON.stringify(d,null,2)+`
1899
- `)}}import y from"fs";import u from"path";function Yo(e,t){if(!y.existsSync(e))return;let o=y.readdirSync(e);for(let n of o){let r=u.join(e,n);y.statSync(r).isDirectory()?Yo(r,t):t(r)}}async function qo(e,t){let o=u.join(e,"package.json");if(!y.existsSync(o))return;let n=JSON.parse(y.readFileSync(o,"utf8"));if(t.orm!=="prisma"){let r=u.join(e,"packages","db");if(y.existsSync(r)){let s=u.join(r,"prisma");y.existsSync(s)&&y.rmSync(s,{recursive:!0,force:!0});let i=u.join(r,"package.json");if(y.existsSync(i)){let a=JSON.parse(y.readFileSync(i,"utf8"));a.dependencies&&delete a.dependencies["@prisma/client"],a.devDependencies&&delete a.devDependencies.prisma,y.writeFileSync(i,JSON.stringify(a,null,2)+`
1900
- `)}let c=u.join(r,"src","index.ts");y.existsSync(c)&&y.writeFileSync(c,`
1894
+ `}}async function Yo(e,t){let o=It.join(e,"packages","commerce","billing");if(!pe.existsSync(o))return;if(t==="none"){$o(o);return}let n=It.join(o,"src"),r=new Set(ra(t));for(let i of oa)r.has(i)||$o(It.join(n,i));let s=It.join(n,"checkout","types.ts");if(pe.existsSync(s)){let i=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",c=pe.readFileSync(s,"utf8"),a=c.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${i}";`);a!==c&&pe.writeFileSync(s,a)}sa(e,ia(t))}import ye from"fs";import pt from"path";var Ho=new Set(["siliconflow","volcengine-ark","bailian","moonshot"]),mn=/@sailor:([^\s*]+)/;function aa(e,t){let{providerIds:o,customEndpoint:n}=t;if(e.startsWith("provider:")){let r=e.slice(9);return{marker:e,keep:o.includes(r)}}if(e==="cn-compatible"){let r=o.some(s=>Ho.has(s));return{marker:e,keep:r||!!n}}if(e.startsWith("cn-instance:")){let r=e.slice(12);return{marker:e,keep:o.includes(r)}}return e==="custom-endpoint"?{marker:e,keep:!!n}:e==="registry-entries"?{marker:e,keep:!0}:{marker:e,keep:!0}}function qo(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function Go(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function Wo(e,t){let o=e.split(`
1895
+ `),n=[],r=e.includes("#"),s=0;for(;s<o.length;){let i=o[s],c=i.match(mn);if(!c){n.push(i),s++;continue}let{marker:a,keep:l}=aa(c[1],t);if(a==="registry-entries"){n.push(r?Go(i):qo(i)),s++;continue}if(l){let u=r?Go(i):qo(i);u.trim().length>0&&n.push(u);let S=s+1;for(;S<o.length&&o[S].trim()!==""&&!mn.test(o[S]);)n.push(o[S]),S++;S<o.length&&o[S].trim()===""&&(n.push(o[S]),S++),s=S}else{let u=s+1;for(;u<o.length&&o[u].trim()!==""&&!mn.test(o[u]);)u++;u<o.length&&o[u].trim()===""&&u++,s=u}}return ca(n.join(`
1896
+ `),t)}function ca(e,t){let{providerIds:o,customEndpoint:n}=t,r=new Set;for(let l of o)["openai","anthropic","google","mistral","xai"].includes(l)&&r.add(l),r.add(l.replace(/-/g,"_")),r.add(l);n&&r.add("custom");let s=/createProviderRegistry\(\{([\s\S]*?)\}\)/,i=e.match(s);if(!i)return e;let a=i[1].split(`
1897
+ `).filter(l=>{let u=l.trim();if(u===""||u.startsWith("//"))return!0;let S=u.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return S?r.has(S[1]):!0}).join(`
1898
+ `);return e.replace(s,`createProviderRegistry({${a}})`)}function pa(e,t){let o=pt.join(t,"registry.ts.template"),n=ye.readFileSync(o,"utf-8");return Wo(n,e)}function la(e,t){let o=pt.join(t,".env.example.template"),n=ye.readFileSync(o,"utf-8");return Wo(n,e)}async function Xo(e,t,o){let n=pa(t,o),r=la(t,o),s=pt.join(e,"packages/ai/agents/src");await ye.promises.mkdir(s,{recursive:!0}),await ye.promises.writeFile(pt.join(s,"registry.ts"),n),await ye.promises.appendFile(pt.join(e,".env.example"),`
1899
+ `+r);let i={ai:"latest"},{providerIds:c,customEndpoint:a}=t;(c.includes("openai")||a||c.some(u=>Ho.has(u)))&&(i["@ai-sdk/openai"]="latest",i["@ai-sdk/openai-compatible"]="latest"),c.includes("anthropic")&&(i["@ai-sdk/anthropic"]="latest"),c.includes("google")&&(i["@ai-sdk/google"]="latest"),c.includes("mistral")&&(i["@ai-sdk/mistral"]="latest"),c.includes("xai")&&(i["@ai-sdk/openai"]="latest");let l=pt.join(e,"package.json");if(ye.existsSync(l)){let u=JSON.parse(await ye.promises.readFile(l,"utf-8"));u.dependencies||(u.dependencies={});for(let[S,I]of Object.entries(i))u.dependencies[S]=I;await ye.promises.writeFile(l,JSON.stringify(u,null,2)+`
1900
+ `)}}import y from"fs";import d from"path";function zo(e,t){if(!y.existsSync(e))return;let o=y.readdirSync(e);for(let n of o){let r=d.join(e,n);y.statSync(r).isDirectory()?zo(r,t):t(r)}}async function Jo(e,t){let o=d.join(e,"package.json");if(!y.existsSync(o))return;let n=JSON.parse(y.readFileSync(o,"utf8"));if(t.orm!=="prisma"){let r=d.join(e,"packages","db");if(y.existsSync(r)){let s=d.join(r,"prisma");y.existsSync(s)&&y.rmSync(s,{recursive:!0,force:!0});let i=d.join(r,"package.json");if(y.existsSync(i)){let a=JSON.parse(y.readFileSync(i,"utf8"));a.dependencies&&delete a.dependencies["@prisma/client"],a.devDependencies&&delete a.devDependencies.prisma,y.writeFileSync(i,JSON.stringify(a,null,2)+`
1901
+ `)}let c=d.join(r,"src","index.ts");y.existsSync(c)&&y.writeFileSync(c,`
1901
1902
  export const prisma = {} as any;
1902
1903
  export const db = {} as any;
1903
1904
  export type PrismaClient = any;
@@ -1943,7 +1944,7 @@ export type UsageAggregate = any;
1943
1944
  export type UsageLedgerEntry = any;
1944
1945
  export type UsageType = any;
1945
1946
  export type UsageLedgerSource = any;
1946
- `)}n.scripts?.postinstall&&(n.scripts.postinstall=n.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let r=u.join(e,"apps");if(y.existsSync(r)){let s=y.readdirSync(r);for(let i of s){let c=u.join(r,i);if(!y.statSync(c).isDirectory())continue;let a=u.join(c,"src","app");if(!y.existsSync(a))continue;["[lang]","[locale]"].forEach(b=>{let m=u.join(a,b);if(y.existsSync(m)){let U=y.readdirSync(m);for(let kt of U)y.renameSync(u.join(m,kt),u.join(a,kt));y.rmdirSync(m)}}),["src/middleware.ts","middleware.ts"].forEach(b=>{let m=u.join(c,b);y.existsSync(m)&&y.rmSync(m)});let l=u.join(c,"src","lib");y.existsSync(l)||y.mkdirSync(l,{recursive:!0});let d=u.join(l,"mock-i18n.ts");y.writeFileSync(d,`
1947
+ `)}n.scripts?.postinstall&&(n.scripts.postinstall=n.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let r=d.join(e,"apps");if(y.existsSync(r)){let s=y.readdirSync(r);for(let i of s){let c=d.join(r,i);if(!y.statSync(c).isDirectory())continue;let a=d.join(c,"src","app");if(!y.existsSync(a))continue;["[lang]","[locale]"].forEach(b=>{let m=d.join(a,b);if(y.existsSync(m)){let M=y.readdirSync(m);for(let xt of M)y.renameSync(d.join(m,xt),d.join(a,xt));y.rmdirSync(m)}}),["src/middleware.ts","middleware.ts"].forEach(b=>{let m=d.join(c,b);y.existsSync(m)&&y.rmSync(m)});let l=d.join(c,"src","lib");y.existsSync(l)||y.mkdirSync(l,{recursive:!0});let u=d.join(l,"mock-i18n.ts");y.writeFileSync(u,`
1947
1948
  import React from 'react';
1948
1949
  export function useTranslations(namespace?: string): any { return (key: string) => key; }
1949
1950
  export function useLocale() { return 'en'; }
@@ -1961,7 +1962,7 @@ export const useRouter = () => ({ push: (...args: any[]) => {}, replace: (...arg
1961
1962
  export default function createMiddleware(...args: any[]) { return (req: any) => req; }
1962
1963
  export function createNavigation(...args: any[]) { return { Link, redirect, usePathname, useRouter, getPathname: () => '/' }; }
1963
1964
  export function defineRouting<T>(config: T): T { return config; }
1964
- `);let C=u.join(l,"mock-i18n.d.ts");y.writeFileSync(C,`declare module '@/lib/mock-i18n' {
1965
+ `);let I=d.join(l,"mock-i18n.d.ts");y.writeFileSync(I,`declare module '@/lib/mock-i18n' {
1965
1966
  export function useTranslations(namespace?: string): any;
1966
1967
  export function useLocale(): string;
1967
1968
  export const NextIntlClientProvider: React.FC<any>;
@@ -1979,19 +1980,19 @@ export function defineRouting<T>(config: T): T { return config; }
1979
1980
  export function createNavigation(...args: any[]): any;
1980
1981
  export function defineRouting<T>(config: T): T;
1981
1982
  }
1982
- `),y.writeFileSync(u.join(l,"mock-i18n-index.ts"),`
1983
+ `),y.writeFileSync(d.join(l,"mock-i18n-index.ts"),`
1983
1984
  export * from './mock-i18n';
1984
1985
  export { default } from './mock-i18n';
1985
- `);let k=u.join(c,"tsconfig.json");if(y.existsSync(k))try{let b=y.readFileSync(k,"utf8");if(b.includes('"paths": {')){let m=b.replace(/"paths":\s*\{/,`"paths": {
1986
+ `);let C=d.join(c,"tsconfig.json");if(y.existsSync(C))try{let b=y.readFileSync(C,"utf8");if(b.includes('"paths": {')){let m=b.replace(/"paths":\s*\{/,`"paths": {
1986
1987
  "next-intl": ["./src/lib/mock-i18n"],
1987
- "next-intl/*": ["./src/lib/mock-i18n"],`);y.writeFileSync(k,m)}}catch{}let $=u.join(c,"src");y.existsSync($)&&Yo($,b=>{if(!b.endsWith(".ts")&&!b.endsWith(".tsx"))return;let m=y.readFileSync(b,"utf8"),U=!1;b.endsWith("src/app/layout.tsx")&&m.includes("../providers")&&(m=m.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),U=!0),m=m.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),m=m.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),m.match(/locale\s*:\s*any/)&&(m=m.replace(/locale\s*:\s*any/g,"locale: string"),U=!0),m.match(/lang\s*:\s*any/)&&(m=m.replace(/lang\s*:\s*any/g,"lang: string"),U=!0),m.match(/requestLocale\s*:\s*any/)&&(m=m.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),U=!0),m.match(/\(locale\s*=\s*(.*)\)/)&&(m=m.replace(/\(locale\s*=\s*(.*)\)/g,"() "),U=!0),m.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(m=m.replace(/export\s+default\s+async\s+function\s+LangLayout\s*\(\s*\{\s*children\s*,\s*params\s*\}\s*:\s*LangLayoutProps\s*\)/g,"export default async function LangLayout({ children }: { children: React.ReactNode })"),U=!0),(b.endsWith("src/app/layout.tsx")||b.endsWith("src/app/sitemap.ts")||b.endsWith("src/app/robots.ts")||b.endsWith("src/components/ui/locale-switcher.tsx")||b.endsWith("src/app/(marketing)/blog/[slug]/page.tsx"))&&(m=m.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),m=m.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),m=m.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),m=m.replace(/\(l\)\s*=>/g,"(l: any) =>"),U=!0),b.endsWith("src/i18n/request.ts")&&(m=m.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),U=!0),(m.match(/locale\s*:/)||m.match(/lang\s*:/))&&(U=!0),U&&y.writeFileSync(b,m)});let ue=u.join(c,"package.json");if(y.existsSync(ue)){let b=JSON.parse(y.readFileSync(ue,"utf8"));b.dependencies&&delete b.dependencies["next-intl"],y.writeFileSync(ue,JSON.stringify(b,null,2)+`
1988
+ "next-intl/*": ["./src/lib/mock-i18n"],`);y.writeFileSync(C,m)}}catch{}let U=d.join(c,"src");y.existsSync(U)&&zo(U,b=>{if(!b.endsWith(".ts")&&!b.endsWith(".tsx"))return;let m=y.readFileSync(b,"utf8"),M=!1;b.endsWith("src/app/layout.tsx")&&m.includes("../providers")&&(m=m.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),M=!0),m=m.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),m=m.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),m.match(/locale\s*:\s*any/)&&(m=m.replace(/locale\s*:\s*any/g,"locale: string"),M=!0),m.match(/lang\s*:\s*any/)&&(m=m.replace(/lang\s*:\s*any/g,"lang: string"),M=!0),m.match(/requestLocale\s*:\s*any/)&&(m=m.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),M=!0),m.match(/\(locale\s*=\s*(.*)\)/)&&(m=m.replace(/\(locale\s*=\s*(.*)\)/g,"() "),M=!0),m.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(m=m.replace(/export\s+default\s+async\s+function\s+LangLayout\s*\(\s*\{\s*children\s*,\s*params\s*\}\s*:\s*LangLayoutProps\s*\)/g,"export default async function LangLayout({ children }: { children: React.ReactNode })"),M=!0),(b.endsWith("src/app/layout.tsx")||b.endsWith("src/app/sitemap.ts")||b.endsWith("src/app/robots.ts")||b.endsWith("src/components/ui/locale-switcher.tsx")||b.endsWith("src/app/(marketing)/blog/[slug]/page.tsx"))&&(m=m.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),m=m.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),m=m.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),m=m.replace(/\(l\)\s*=>/g,"(l: any) =>"),M=!0),b.endsWith("src/i18n/request.ts")&&(m=m.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),M=!0),(m.match(/locale\s*:/)||m.match(/lang\s*:/))&&(M=!0),M&&y.writeFileSync(b,m)});let ue=d.join(c,"package.json");if(y.existsSync(ue)){let b=JSON.parse(y.readFileSync(ue,"utf8"));b.dependencies&&delete b.dependencies["next-intl"],y.writeFileSync(ue,JSON.stringify(b,null,2)+`
1988
1989
  `)}}}}y.writeFileSync(o,JSON.stringify(n,null,2)+`
1989
- `)}function v(e){try{y.rmSync(e,{recursive:!0,force:!0})}catch{}}function ta(e,t){if(!y.existsSync(e))return;let o;try{o=JSON.parse(y.readFileSync(e,"utf8"))}catch{return}let n=!1;if(o.dependencies&&t in o.dependencies){let{[t]:r,...s}=o.dependencies;o={...o,dependencies:s},n=!0}if(o.devDependencies&&t in o.devDependencies){let{[t]:r,...s}=o.devDependencies;o={...o,devDependencies:s},n=!0}n&&y.writeFileSync(e,JSON.stringify(o,null,2)+`
1990
- `)}function Go(e,t){t.cronJobs||(v(u.join(e,"apps/web/src/app/api/cron")),v(u.join(e,"packages/integrations/queue/src/scheduled"))),t.auditLog||(v(u.join(e,"apps/web/src/app/[locale]/(app)/settings/audit-log")),v(u.join(e,"apps/web/src/app/api/audit-logs")),v(u.join(e,"apps/web/src/components/audit"))),t.apiKeys||(v(u.join(e,"apps/web/src/app/[locale]/(app)/settings/api-keys")),v(u.join(e,"apps/web/src/app/api/api-keys")),v(u.join(e,"apps/web/src/components/api-keys"))),t.webhooks||(v(u.join(e,"apps/web/src/app/[locale]/(app)/settings/webhooks")),v(u.join(e,"apps/web/src/app/api/webhooks")),v(u.join(e,"apps/web/src/components/webhooks")),v(u.join(e,"packages/integrations/webhooks"))),t.commandPalette||(v(u.join(e,"apps/web/src/components/command-palette")),v(u.join(e,"apps/web/src/app/[locale]/providers/command-palette-mount.tsx"))),t.cookieConsent||(v(u.join(e,"apps/landing-page/src/components/cookie-consent-banner.tsx")),v(u.join(e,"apps/landing-page/src/components/__tests__/cookie-consent-banner.test.tsx")),v(u.join(e,"apps/landing-page/src/lib/cookie-consent.ts")),v(u.join(e,"apps/landing-page/src/lib/__tests__/cookie-consent.test.ts")),v(u.join(e,"apps/web/src/app/api/cookie-consent"))),t.legalPages||(v(u.join(e,"apps/landing-page/src/app/[lang]/(legal)/legal")),v(u.join(e,"apps/landing-page/src/lib/legal-documents.ts")),v(u.join(e,"apps/landing-page/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(v(u.join(e,"packages/ops/china-compliance")),v(u.join(e,"apps/landing-page/src/components/icp-footer.tsx")),v(u.join(e,"apps/landing-page/src/components/__tests__/icp-footer.test.tsx")),v(u.join(e,"apps/web/src/components/auth/wechat-login-button.tsx")),v(u.join(e,"apps/web/src/components/auth/__tests__/wechat-login-button.test.tsx")),ta(u.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import lt from"fs";import Ho from"path";var Wo=/^--\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/m;function na(e){let t=Wo.exec(e);if(!t)return null;let[,o,n]=t,r=n.split("|").map(s=>s.trim()).filter(Boolean);return{flag:o,values:r}}function oa(e){return e.replace(Wo,"").replace(/^\n/,"")}function mn(e,t){let o={kept:[],removed:[],skipped:[]};if(!lt.existsSync(e))return o;let n=lt.readdirSync(e,{withFileTypes:!0}).filter(r=>r.isDirectory()).sort((r,s)=>r.name.localeCompare(s.name));for(let r of n){let s=Ho.join(e,r.name),i=Ho.join(s,"migration.sql");if(!lt.existsSync(i)){o.skipped.push(r.name);continue}let c=lt.readFileSync(i,"utf8"),a=na(c);if(!a){o.skipped.push(r.name);continue}let l=t[a.flag];if(l!==void 0&&a.values.includes(l)){lt.writeFileSync(i,oa(c)),o.kept.push(r.name);continue}lt.rmSync(s,{recursive:!0,force:!0}),o.removed.push(r.name)}return o}import{getSchema as ra,printSchema as sa}from"@mrleebo/prisma-ast";var ia=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function aa(e){return e.type==="comment"&&e.text.trim().startsWith("//")}function ca(e){let t=ia.exec(e.trim());if(!t)return null;let[,o,n]=t,r=n.split("|").map(s=>s.trim()).filter(s=>s.length>0);return{flag:o,values:r}}function pa(e,t){for(let o=t-1;o>=0;o--){let n=e[o];if(n.type==="comment"){let r=ca(n.text);if(r)return{annIndex:o,parsed:r};continue}break}return null}function la(e){return e.type==="model"||e.type==="enum"}function gn(e,t){let o=ra(e),n=new Set;for(let c=0;c<o.list.length;c++){let a=o.list[c];if(!la(a))continue;let l=pa(o.list,c);if(!l)continue;let d=t[l.parsed.flag];if(d!==void 0&&l.parsed.values.includes(d))n.add(l.annIndex);else{n.add(c);for(let k=c-1;k>=0;k--){let $=o.list[k];if(aa($)){n.add(k);continue}break}let C=o.list[c+1];C&&C.type==="break"&&n.add(c+1)}}let r=o.list.filter((c,a)=>!n.has(a)),s=[];for(let c of r){let a=s[s.length-1];c.type==="break"&&a&&a.type==="break"||s.push(c)}return sa({type:"schema",list:s})}import dt from"fs";import zo from"path";var Wt=[{id:"qstash",name:"Upstash QStash",region:"both",envVars:["QSTASH_TOKEN","QSTASH_CURRENT_SIGNING_KEY","QSTASH_NEXT_SIGNING_KEY"],docs:"https://upstash.com/docs/qstash",description:"Serverless HTTP-based queue"},{id:"bullmq",name:"BullMQ",region:"both",envVars:["REDIS_URL"],docs:"https://docs.bullmq.io",description:"Redis-backed job queue"},{id:"sqs",name:"AWS SQS",region:"global",envVars:["AWS_SQS_QUEUE_URL","AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_REGION"],docs:"https://docs.aws.amazon.com/AWSSimpleQueueService/",description:"AWS managed queue"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip queue package"}];function Xo(e){return Wt.find(t=>t.id===e)}var jl=Wt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Jo(e){return dt.existsSync(e)?dt.readFileSync(e,"utf-8"):null}function da(e,t){let o=zo.join(e,".env.example"),n=Jo(o);if(n===null)return;let r=`# Queue: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1991
- `);dt.appendFileSync(o,s)}function ua(e,t,o){let n=zo.join(e,".env.example"),r=Jo(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?dt.writeFileSync(n,r.replace(s,`${t}="${o}"`)):dt.appendFileSync(n,`${t}="${o}"
1992
- `)}async function Qo(e,t,o){let n=Re(e,"queue");if(t==="none"){n&&dt.rmSync(n,{recursive:!0,force:!0});return}let r=Xo(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${Wt.map(s=>s.id).join(", ")}`);n&&(da(e,r),ua(e,"QUEUE_PROVIDER",t))}import le from"fs";import Se from"path";import{fileURLToPath as ma}from"url";var ga=ma(import.meta.url),Zo=Se.dirname(ga),fa=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|toml|py)$/,ya=["backends/gateway","infra","e2e","tests"];function Sa(){let e=[Se.join(Zo,"..","templates"),Se.join(Zo,"..","..","templates")];for(let t of e)if(le.existsSync(t))return t;return e[0]}async function er(e,t){let o=Sa(),n=[],r=[],s=[...ya,...t.withWorkflows?["workflows"]:[],...t.withPythonBackend?["backends/python"]:[]];for(let i of s){let c=Se.join(o,i);if(!le.existsSync(c)){r.push(i);continue}let a=Se.join(e,i);tr(c,a),nr(a,{"{PRODUCT_NAME}":t.projectName}),n.push(i)}return{applied:n,skipped:r}}function tr(e,t){le.mkdirSync(t,{recursive:!0});for(let o of le.readdirSync(e,{withFileTypes:!0})){let n=Se.join(e,o.name),r=Se.join(t,o.name);o.isDirectory()?tr(n,r):le.existsSync(r)||le.copyFileSync(n,r)}}function nr(e,t){for(let o of le.readdirSync(e,{withFileTypes:!0})){let n=Se.join(e,o.name);if(o.isDirectory()){nr(n,t);continue}if(!fa.test(o.name))continue;let r=le.readFileSync(n,"utf-8"),s=!1;for(let[i,c]of Object.entries(t))r.includes(i)&&(r=r.split(i).join(c),s=!0);s&&le.writeFileSync(n,r)}}import ut from"fs";import rr from"path";var Xt=[{id:"meilisearch",name:"Meilisearch",region:"both",envVars:["MEILISEARCH_HOST","MEILISEARCH_MASTER_KEY"],docs:"https://docs.meilisearch.com",description:"Self-hostable search"},{id:"typesense",name:"Typesense",region:"both",envVars:["TYPESENSE_HOST","TYPESENSE_PORT","TYPESENSE_PROTOCOL","TYPESENSE_API_KEY"],docs:"https://typesense.org/docs",description:"Open-source search"},{id:"algolia",name:"Algolia",region:"global",envVars:["ALGOLIA_APP_ID","ALGOLIA_ADMIN_API_KEY","ALGOLIA_SEARCH_API_KEY"],docs:"https://www.algolia.com/doc/",description:"Managed search as a service"},{id:"pgvector",name:"pgvector (Postgres)",region:"both",envVars:["DATABASE_URL"],docs:"https://github.com/pgvector/pgvector",description:"Postgres vector + full-text"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip search package"}];function or(e){return Xt.find(t=>t.id===e)}var zl=Xt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function sr(e){return ut.existsSync(e)?ut.readFileSync(e,"utf-8"):null}function ha(e,t){let o=rr.join(e,".env.example"),n=sr(o);if(n===null)return;let r=`# Search: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1993
- `);ut.appendFileSync(o,s)}function Ea(e,t,o){let n=rr.join(e,".env.example"),r=sr(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?ut.writeFileSync(n,r.replace(s,`${t}="${o}"`)):ut.appendFileSync(n,`${t}="${o}"
1994
- `)}async function ir(e,t,o){let n=Re(e,"search");if(t==="none"){n&&ut.rmSync(n,{recursive:!0,force:!0});return}let r=or(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${Xt.map(s=>s.id).join(", ")}`);n&&(ha(e,r),Ea(e,"SEARCH_PROVIDER",t))}import he from"fs";import Me from"path";function va(e){let t=[Me.join(e,"packages","db"),Me.join(e,"apps","web")];for(let o of t){let n=Me.join(o,"prisma","schema.prisma");if(he.existsSync(n))return{packageDir:o,seedPath:Me.join(o,"prisma","seed.ts"),packageJsonPath:Me.join(o,"package.json")}}return null}function _a(e){try{let t=he.readFileSync(e,"utf8"),o=new Set,n=/^\s*model\s+(\w+)\s*\{/gm,r=n.exec(t);for(;r;)o.add(r[1]),r=n.exec(t);return o}catch{return new Set}}function ba(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
1990
+ `)}function v(e){try{y.rmSync(e,{recursive:!0,force:!0})}catch{}}function da(e,t){if(!y.existsSync(e))return;let o;try{o=JSON.parse(y.readFileSync(e,"utf8"))}catch{return}let n=!1;if(o.dependencies&&t in o.dependencies){let{[t]:r,...s}=o.dependencies;o={...o,dependencies:s},n=!0}if(o.devDependencies&&t in o.devDependencies){let{[t]:r,...s}=o.devDependencies;o={...o,devDependencies:s},n=!0}n&&y.writeFileSync(e,JSON.stringify(o,null,2)+`
1991
+ `)}function Qo(e,t){t.cronJobs||(v(d.join(e,"apps/web/src/app/api/cron")),v(d.join(e,"packages/integrations/queue/src/scheduled"))),t.auditLog||(v(d.join(e,"apps/web/src/app/[locale]/(app)/settings/audit-log")),v(d.join(e,"apps/web/src/app/api/audit-logs")),v(d.join(e,"apps/web/src/components/audit"))),t.apiKeys||(v(d.join(e,"apps/web/src/app/[locale]/(app)/settings/api-keys")),v(d.join(e,"apps/web/src/app/api/api-keys")),v(d.join(e,"apps/web/src/components/api-keys"))),t.webhooks||(v(d.join(e,"apps/web/src/app/[locale]/(app)/settings/webhooks")),v(d.join(e,"apps/web/src/app/api/webhooks")),v(d.join(e,"apps/web/src/components/webhooks")),v(d.join(e,"packages/integrations/webhooks"))),t.commandPalette||(v(d.join(e,"apps/web/src/components/command-palette")),v(d.join(e,"apps/web/src/app/[locale]/providers/command-palette-mount.tsx"))),t.cookieConsent||(v(d.join(e,"apps/landing-page/src/components/cookie-consent-banner.tsx")),v(d.join(e,"apps/landing-page/src/components/__tests__/cookie-consent-banner.test.tsx")),v(d.join(e,"apps/landing-page/src/lib/cookie-consent.ts")),v(d.join(e,"apps/landing-page/src/lib/__tests__/cookie-consent.test.ts")),v(d.join(e,"apps/web/src/app/api/cookie-consent"))),t.legalPages||(v(d.join(e,"apps/landing-page/src/app/[lang]/(legal)/legal")),v(d.join(e,"apps/landing-page/src/lib/legal-documents.ts")),v(d.join(e,"apps/landing-page/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(v(d.join(e,"packages/ops/china-compliance")),v(d.join(e,"apps/landing-page/src/components/icp-footer.tsx")),v(d.join(e,"apps/landing-page/src/components/__tests__/icp-footer.test.tsx")),v(d.join(e,"apps/web/src/components/auth/wechat-login-button.tsx")),v(d.join(e,"apps/web/src/components/auth/__tests__/wechat-login-button.test.tsx")),da(d.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import lt from"fs";import Zo from"path";var er=/^--\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/m;function ua(e){let t=er.exec(e);if(!t)return null;let[,o,n]=t,r=n.split("|").map(s=>s.trim()).filter(Boolean);return{flag:o,values:r}}function ma(e){return e.replace(er,"").replace(/^\n/,"")}function gn(e,t){let o={kept:[],removed:[],skipped:[]};if(!lt.existsSync(e))return o;let n=lt.readdirSync(e,{withFileTypes:!0}).filter(r=>r.isDirectory()).sort((r,s)=>r.name.localeCompare(s.name));for(let r of n){let s=Zo.join(e,r.name),i=Zo.join(s,"migration.sql");if(!lt.existsSync(i)){o.skipped.push(r.name);continue}let c=lt.readFileSync(i,"utf8"),a=ua(c);if(!a){o.skipped.push(r.name);continue}let l=t[a.flag];if(l!==void 0&&a.values.includes(l)){lt.writeFileSync(i,ma(c)),o.kept.push(r.name);continue}lt.rmSync(s,{recursive:!0,force:!0}),o.removed.push(r.name)}return o}import{getSchema as ga,printSchema as fa}from"@mrleebo/prisma-ast";var ya=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function Sa(e){return e.type==="comment"&&e.text.trim().startsWith("//")}function ha(e){let t=ya.exec(e.trim());if(!t)return null;let[,o,n]=t,r=n.split("|").map(s=>s.trim()).filter(s=>s.length>0);return{flag:o,values:r}}function Ea(e,t){for(let o=t-1;o>=0;o--){let n=e[o];if(n.type==="comment"){let r=ha(n.text);if(r)return{annIndex:o,parsed:r};continue}break}return null}function va(e){return e.type==="model"||e.type==="enum"}function fn(e,t){let o=ga(e),n=new Set;for(let c=0;c<o.list.length;c++){let a=o.list[c];if(!va(a))continue;let l=Ea(o.list,c);if(!l)continue;let u=t[l.parsed.flag];if(u!==void 0&&l.parsed.values.includes(u))n.add(l.annIndex);else{n.add(c);for(let C=c-1;C>=0;C--){let U=o.list[C];if(Sa(U)){n.add(C);continue}break}let I=o.list[c+1];I&&I.type==="break"&&n.add(c+1)}}let r=o.list.filter((c,a)=>!n.has(a)),s=[];for(let c of r){let a=s[s.length-1];c.type==="break"&&a&&a.type==="break"||s.push(c)}return fa({type:"schema",list:s})}import dt from"fs";import nr from"path";var Xt=[{id:"qstash",name:"Upstash QStash",region:"both",envVars:["QSTASH_TOKEN","QSTASH_CURRENT_SIGNING_KEY","QSTASH_NEXT_SIGNING_KEY"],docs:"https://upstash.com/docs/qstash",description:"Serverless HTTP-based queue"},{id:"bullmq",name:"BullMQ",region:"both",envVars:["REDIS_URL"],docs:"https://docs.bullmq.io",description:"Redis-backed job queue"},{id:"sqs",name:"AWS SQS",region:"global",envVars:["AWS_SQS_QUEUE_URL","AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_REGION"],docs:"https://docs.aws.amazon.com/AWSSimpleQueueService/",description:"AWS managed queue"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip queue package"}];function tr(e){return Xt.find(t=>t.id===e)}var nd=Xt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function or(e){return dt.existsSync(e)?dt.readFileSync(e,"utf-8"):null}function _a(e,t){let o=nr.join(e,".env.example"),n=or(o);if(n===null)return;let r=`# Queue: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1992
+ `);dt.appendFileSync(o,s)}function ba(e,t,o){let n=nr.join(e,".env.example"),r=or(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?dt.writeFileSync(n,r.replace(s,`${t}="${o}"`)):dt.appendFileSync(n,`${t}="${o}"
1993
+ `)}async function rr(e,t,o){let n=Re(e,"queue");if(t==="none"){n&&dt.rmSync(n,{recursive:!0,force:!0});return}let r=tr(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${Xt.map(s=>s.id).join(", ")}`);n&&(_a(e,r),ba(e,"QUEUE_PROVIDER",t))}import le from"fs";import Se from"path";import{fileURLToPath as Pa}from"url";var Aa=Pa(import.meta.url),sr=Se.dirname(Aa),Ca=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|toml|py)$/,Ia=["backends/gateway","infra","e2e","tests"];function wa(){let e=[Se.join(sr,"..","templates"),Se.join(sr,"..","..","templates")];for(let t of e)if(le.existsSync(t))return t;return e[0]}async function ir(e,t){let o=wa(),n=[],r=[],s=[...Ia,...t.withWorkflows?["workflows"]:[],...t.withPythonBackend?["backends/python"]:[]];for(let i of s){let c=Se.join(o,i);if(!le.existsSync(c)){r.push(i);continue}let a=Se.join(e,i);ar(c,a),cr(a,{"{PRODUCT_NAME}":t.projectName}),n.push(i)}return{applied:n,skipped:r}}function ar(e,t){le.mkdirSync(t,{recursive:!0});for(let o of le.readdirSync(e,{withFileTypes:!0})){let n=Se.join(e,o.name),r=Se.join(t,o.name);o.isDirectory()?ar(n,r):le.existsSync(r)||le.copyFileSync(n,r)}}function cr(e,t){for(let o of le.readdirSync(e,{withFileTypes:!0})){let n=Se.join(e,o.name);if(o.isDirectory()){cr(n,t);continue}if(!Ca.test(o.name))continue;let r=le.readFileSync(n,"utf-8"),s=!1;for(let[i,c]of Object.entries(t))r.includes(i)&&(r=r.split(i).join(c),s=!0);s&&le.writeFileSync(n,r)}}import ut from"fs";import lr from"path";var zt=[{id:"meilisearch",name:"Meilisearch",region:"both",envVars:["MEILISEARCH_HOST","MEILISEARCH_MASTER_KEY"],docs:"https://docs.meilisearch.com",description:"Self-hostable search"},{id:"typesense",name:"Typesense",region:"both",envVars:["TYPESENSE_HOST","TYPESENSE_PORT","TYPESENSE_PROTOCOL","TYPESENSE_API_KEY"],docs:"https://typesense.org/docs",description:"Open-source search"},{id:"algolia",name:"Algolia",region:"global",envVars:["ALGOLIA_APP_ID","ALGOLIA_ADMIN_API_KEY","ALGOLIA_SEARCH_API_KEY"],docs:"https://www.algolia.com/doc/",description:"Managed search as a service"},{id:"pgvector",name:"pgvector (Postgres)",region:"both",envVars:["DATABASE_URL"],docs:"https://github.com/pgvector/pgvector",description:"Postgres vector + full-text"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip search package"}];function pr(e){return zt.find(t=>t.id===e)}var md=zt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function dr(e){return ut.existsSync(e)?ut.readFileSync(e,"utf-8"):null}function Ra(e,t){let o=lr.join(e,".env.example"),n=dr(o);if(n===null)return;let r=`# Search: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1994
+ `);ut.appendFileSync(o,s)}function ka(e,t,o){let n=lr.join(e,".env.example"),r=dr(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?ut.writeFileSync(n,r.replace(s,`${t}="${o}"`)):ut.appendFileSync(n,`${t}="${o}"
1995
+ `)}async function ur(e,t,o){let n=Re(e,"search");if(t==="none"){n&&ut.rmSync(n,{recursive:!0,force:!0});return}let r=pr(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${zt.map(s=>s.id).join(", ")}`);n&&(Ra(e,r),ka(e,"SEARCH_PROVIDER",t))}import he from"fs";import Me from"path";function xa(e){let t=[Me.join(e,"packages","db"),Me.join(e,"apps","web")];for(let o of t){let n=Me.join(o,"prisma","schema.prisma");if(he.existsSync(n))return{packageDir:o,seedPath:Me.join(o,"prisma","seed.ts"),packageJsonPath:Me.join(o,"package.json")}}return null}function Na(e){try{let t=he.readFileSync(e,"utf8"),o=new Set,n=/^\s*model\s+(\w+)\s*\{/gm,r=n.exec(t);for(;r;)o.add(r[1]),r=n.exec(t);return o}catch{return new Set}}function Ta(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
1995
1996
  const admin = await prisma.user.create({
1996
1997
  data: {
1997
1998
  clerkId: "user_mock_admin",
@@ -2022,7 +2023,7 @@ export { default } from './mock-i18n';
2022
2023
  console.log("\\u2713 Created admin user:", admin.email);
2023
2024
  } catch (err) {
2024
2025
  console.warn("\\u26A0 Admin user creation skipped:", (err as Error).message);
2025
- }`}function Pa(e,t){let o=t.has("Tenant"),n=t.has("User"),r=t.has("Project"),s=ba(e,n),i=o?` let tenants: Array<{ id: string; name: string }> = [];
2026
+ }`}function Oa(e,t){let o=t.has("Tenant"),n=t.has("User"),r=t.has("Project"),s=Ta(e,n),i=o?` let tenants: Array<{ id: string; name: string }> = [];
2026
2027
  try {
2027
2028
  tenants = await Promise.all([
2028
2029
  prisma.tenant.create({
@@ -2091,12 +2092,12 @@ main()
2091
2092
  .finally(async () => {
2092
2093
  await prisma.$disconnect();
2093
2094
  });
2094
- `}function Aa(e){if(he.existsSync(e))try{let t=he.readFileSync(e,"utf8"),o=JSON.parse(t),n=o.scripts??{},r=!1;n["db:seed"]||(n["db:seed"]="prisma db seed",r=!0);let s=o.prisma??{};if(s.seed||(s.seed="tsx prisma/seed.ts",r=!0),!r)return;let i={...o,scripts:n,prisma:s};he.writeFileSync(e,JSON.stringify(i,null,2)+`
2095
- `)}catch(t){let o=t instanceof Error?t.message:String(t);console.warn(`[create-sailor] Failed to patch seed scripts in ${e}: ${o}`)}}async function ar(e,t){let o=va(e);if(o)try{let n=Me.join(o.packageDir,"prisma","schema.prisma"),r=_a(n),s=Pa(t,r),i=Me.dirname(o.seedPath);he.existsSync(i)||he.mkdirSync(i,{recursive:!0}),he.writeFileSync(o.seedPath,s),Aa(o.packageJsonPath)}catch(n){let r=n instanceof Error?n.message:String(n);throw console.error(`[create-sailor] Failed to generate seed data: ${r}`),new Error(`Unable to write prisma/seed.ts: ${r}`)}}import Ee from"fs";import De from"path";var zt=[{id:"twilio",name:"Twilio",region:"global",envVars:["TWILIO_ACCOUNT_SID","TWILIO_AUTH_TOKEN","TWILIO_FROM_NUMBER"],docs:"https://www.twilio.com/docs/sms",pkgs:["twilio"]},{id:"messagebird",name:"MessageBird (Bird)",region:"global",envVars:["MESSAGEBIRD_ACCESS_KEY","MESSAGEBIRD_ORIGINATOR"],docs:"https://developers.messagebird.com/api/sms-messaging/",pkgs:["messagebird"]},{id:"plivo",name:"Plivo",region:"global",envVars:["PLIVO_AUTH_ID","PLIVO_AUTH_TOKEN","PLIVO_FROM_NUMBER"],docs:"https://www.plivo.com/docs/sms/",pkgs:["plivo"]},{id:"aliyun-sms",name:"\u963F\u91CC\u4E91\u77ED\u4FE1 Aliyun SMS",region:"cn",envVars:["ALIYUN_SMS_ACCESS_KEY","ALIYUN_SMS_ACCESS_SECRET","ALIYUN_SMS_SIGN_NAME","ALIYUN_SMS_TEMPLATE_CODE","ALIYUN_SMS_ENDPOINT"],docs:"https://help.aliyun.com/product/44282.html",pkgs:["@alicloud/dysmsapi20170525","@alicloud/openapi-client"]},{id:"tencent-sms",name:"\u817E\u8BAF\u4E91\u77ED\u4FE1 Tencent SMS",region:"cn",envVars:["TENCENT_SMS_SECRET_ID","TENCENT_SMS_SECRET_KEY","TENCENT_SMS_SDK_APP_ID","TENCENT_SMS_SIGN_NAME","TENCENT_SMS_TEMPLATE_ID","TENCENT_SMS_REGION"],docs:"https://cloud.tencent.com/document/product/382",pkgs:["tencentcloud-sdk-nodejs-sms"]},{id:"yunpian",name:"\u4E91\u7247 Yunpian",region:"cn",envVars:["YUNPIAN_API_KEY","YUNPIAN_SIGN"],docs:"https://www.yunpian.com/official/document/sms/zh_CN/introduction_product_intro",pkgs:["yunpian-nodejs-sdk"]},{id:"none",name:"None",region:"both",envVars:[],docs:""}],id=zt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function cr(e){return zt.find(t=>t.id===e)}var Ca="@nebutra/sms",Ia={twilio:"^5.3.6",messagebird:"^4.0.1",plivo:"^4.73.0","@alicloud/dysmsapi20170525":"^2.0.24","@alicloud/openapi-client":"^0.4.12","tencentcloud-sdk-nodejs-sms":"^4.0.970","yunpian-nodejs-sdk":"^0.0.2"};function fn(e,t){Ee.mkdirSync(De.dirname(e),{recursive:!0}),Ee.writeFileSync(e,t)}function wa(e,t){let o=De.join(e,".env.example");Ee.existsSync(o)?Ee.appendFileSync(o,`
2096
- `+t):Ee.writeFileSync(o,t)}function Ra(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2095
+ `}function La(e){if(he.existsSync(e))try{let t=he.readFileSync(e,"utf8"),o=JSON.parse(t),n=o.scripts??{},r=!1;n["db:seed"]||(n["db:seed"]="prisma db seed",r=!0);let s=o.prisma??{};if(s.seed||(s.seed="tsx prisma/seed.ts",r=!0),!r)return;let i={...o,scripts:n,prisma:s};he.writeFileSync(e,JSON.stringify(i,null,2)+`
2096
+ `)}catch(t){let o=t instanceof Error?t.message:String(t);console.warn(`[create-sailor] Failed to patch seed scripts in ${e}: ${o}`)}}async function mr(e,t){let o=xa(e);if(o)try{let n=Me.join(o.packageDir,"prisma","schema.prisma"),r=Na(n),s=Oa(t,r),i=Me.dirname(o.seedPath);he.existsSync(i)||he.mkdirSync(i,{recursive:!0}),he.writeFileSync(o.seedPath,s),La(o.packageJsonPath)}catch(n){let r=n instanceof Error?n.message:String(n);throw console.error(`[create-sailor] Failed to generate seed data: ${r}`),new Error(`Unable to write prisma/seed.ts: ${r}`)}}import Ee from"fs";import De from"path";var Jt=[{id:"twilio",name:"Twilio",region:"global",envVars:["TWILIO_ACCOUNT_SID","TWILIO_AUTH_TOKEN","TWILIO_FROM_NUMBER"],docs:"https://www.twilio.com/docs/sms",pkgs:["twilio"]},{id:"messagebird",name:"MessageBird (Bird)",region:"global",envVars:["MESSAGEBIRD_ACCESS_KEY","MESSAGEBIRD_ORIGINATOR"],docs:"https://developers.messagebird.com/api/sms-messaging/",pkgs:["messagebird"]},{id:"plivo",name:"Plivo",region:"global",envVars:["PLIVO_AUTH_ID","PLIVO_AUTH_TOKEN","PLIVO_FROM_NUMBER"],docs:"https://www.plivo.com/docs/sms/",pkgs:["plivo"]},{id:"aliyun-sms",name:"\u963F\u91CC\u4E91\u77ED\u4FE1 Aliyun SMS",region:"cn",envVars:["ALIYUN_SMS_ACCESS_KEY","ALIYUN_SMS_ACCESS_SECRET","ALIYUN_SMS_SIGN_NAME","ALIYUN_SMS_TEMPLATE_CODE","ALIYUN_SMS_ENDPOINT"],docs:"https://help.aliyun.com/product/44282.html",pkgs:["@alicloud/dysmsapi20170525","@alicloud/openapi-client"]},{id:"tencent-sms",name:"\u817E\u8BAF\u4E91\u77ED\u4FE1 Tencent SMS",region:"cn",envVars:["TENCENT_SMS_SECRET_ID","TENCENT_SMS_SECRET_KEY","TENCENT_SMS_SDK_APP_ID","TENCENT_SMS_SIGN_NAME","TENCENT_SMS_TEMPLATE_ID","TENCENT_SMS_REGION"],docs:"https://cloud.tencent.com/document/product/382",pkgs:["tencentcloud-sdk-nodejs-sms"]},{id:"yunpian",name:"\u4E91\u7247 Yunpian",region:"cn",envVars:["YUNPIAN_API_KEY","YUNPIAN_SIGN"],docs:"https://www.yunpian.com/official/document/sms/zh_CN/introduction_product_intro",pkgs:["yunpian-nodejs-sdk"]},{id:"none",name:"None",region:"both",envVars:[],docs:""}],Pd=Jt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function gr(e){return Jt.find(t=>t.id===e)}var Ua="@nebutra/sms",Ma={twilio:"^5.3.6",messagebird:"^4.0.1",plivo:"^4.73.0","@alicloud/dysmsapi20170525":"^2.0.24","@alicloud/openapi-client":"^0.4.12","tencentcloud-sdk-nodejs-sms":"^4.0.970","yunpian-nodejs-sdk":"^0.0.2"};function yn(e,t){Ee.mkdirSync(De.dirname(e),{recursive:!0}),Ee.writeFileSync(e,t)}function Da(e,t){let o=De.join(e,".env.example");Ee.existsSync(o)?Ee.appendFileSync(o,`
2097
+ `+t):Ee.writeFileSync(o,t)}function Fa(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2097
2098
  `);return`${t}
2098
2099
  ${o}
2099
- `}var ka=`/**
2100
+ `}var ja=`/**
2100
2101
  * Inputs for the \`sendSms\` wrapper. Keep this surface portable across
2101
2102
  * providers \u2014 provider-specific options belong in the wrapper itself.
2102
2103
  */
@@ -2116,7 +2117,7 @@ export interface SendSmsResult {
2116
2117
  provider: string;
2117
2118
  raw?: unknown;
2118
2119
  }
2119
- `;function xa(){return`import twilio from "twilio";
2120
+ `;function Va(){return`import twilio from "twilio";
2120
2121
  import type { SendSmsInput, SendSmsResult } from "./types";
2121
2122
 
2122
2123
  let client: ReturnType<typeof twilio> | null = null;
@@ -2151,7 +2152,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2151
2152
  }
2152
2153
 
2153
2154
  export type { SendSmsInput, SendSmsResult } from "./types";
2154
- `}function Na(){return`import messagebird from "messagebird";
2155
+ `}function Ba(){return`import messagebird from "messagebird";
2155
2156
  import type { SendSmsInput, SendSmsResult } from "./types";
2156
2157
 
2157
2158
  let client: ReturnType<typeof messagebird> | null = null;
@@ -2189,7 +2190,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2189
2190
  }
2190
2191
 
2191
2192
  export type { SendSmsInput, SendSmsResult } from "./types";
2192
- `}function Ta(){return`import plivo from "plivo";
2193
+ `}function Ka(){return`import plivo from "plivo";
2193
2194
  import type { SendSmsInput, SendSmsResult } from "./types";
2194
2195
 
2195
2196
  let client: InstanceType<typeof plivo.Client> | null = null;
@@ -2228,7 +2229,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2228
2229
  }
2229
2230
 
2230
2231
  export type { SendSmsInput, SendSmsResult } from "./types";
2231
- `}function Oa(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2232
+ `}function $a(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2232
2233
  import * as $OpenApi from "@alicloud/openapi-client";
2233
2234
  import type { SendSmsInput, SendSmsResult } from "./types";
2234
2235
 
@@ -2277,7 +2278,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2277
2278
  }
2278
2279
 
2279
2280
  export type { SendSmsInput, SendSmsResult } from "./types";
2280
- `}function La(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2281
+ `}function Ya(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2281
2282
  import type { SendSmsInput, SendSmsResult } from "./types";
2282
2283
 
2283
2284
  const SmsClient = tencentcloud.sms.v20210111.Client;
@@ -2342,7 +2343,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2342
2343
  }
2343
2344
 
2344
2345
  export type { SendSmsInput, SendSmsResult } from "./types";
2345
- `}function Ua(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2346
+ `}function qa(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2346
2347
  import Yunpian from "yunpian-nodejs-sdk";
2347
2348
  import type { SendSmsInput, SendSmsResult } from "./types";
2348
2349
 
@@ -2394,13 +2395,13 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2394
2395
  }
2395
2396
 
2396
2397
  export type { SendSmsInput, SendSmsResult } from "./types";
2397
- `}function Ma(e){switch(e){case"twilio":return xa();case"messagebird":return Na();case"plivo":return Ta();case"aliyun-sms":return Oa();case"tencent-sms":return La();case"yunpian":return Ua();case"none":return`export {};
2398
- `}}function Da(e){let t={};for(let n of e.pkgs??[]){let r=Ia[n];r&&(t[n]=r)}let o={name:Ca,version:"0.1.0",private:!0,description:`Transactional SMS via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(o,null,2)+`
2399
- `}async function pr(e,t,o="global"){if(t==="none")return;let n=cr(t);if(!n)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${zt.map(i=>i.id).join(", ")}`);let r=De.join(e,"packages","sms");if(!Ee.existsSync(r))return;let s=De.join(r,"src");Ee.existsSync(s)&&Ee.rmSync(s,{recursive:!0,force:!0});try{fn(De.join(r,"package.json"),Da(n)),fn(De.join(s,"types.ts"),ka),fn(De.join(s,"index.ts"),Ma(n.id)),wa(e,Ra(n))}catch(i){throw console.error(`Failed to apply SMS selection "${t}":`,i),new Error(`SMS scaffold for "${t}" failed \u2014 see stderr for details.`)}}import je from"fs";import Fe from"path";var It=[{id:"r2",name:"Cloudflare R2",region:"global",envVars:["R2_ACCOUNT_ID","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY","R2_BUCKET"],docs:"https://developers.cloudflare.com/r2/api/s3/api/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"s3",name:"AWS S3",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_S3_REGION","S3_BUCKET"],docs:"https://docs.aws.amazon.com/s3/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"supabase-storage",name:"Supabase Storage",region:"global",envVars:["SUPABASE_URL","SUPABASE_SERVICE_ROLE_KEY","SUPABASE_BUCKET"],docs:"https://supabase.com/docs/guides/storage",pkg:"@supabase/supabase-js",pkgVersion:"^2.45.4"},{id:"aliyun-oss",name:"\u963F\u91CC\u4E91 OSS",region:"cn",envVars:["ALIYUN_OSS_ACCESS_KEY","ALIYUN_OSS_ACCESS_SECRET","ALIYUN_OSS_REGION","ALIYUN_OSS_BUCKET"],docs:"https://help.aliyun.com/product/31815.html",pkg:"ali-oss",pkgVersion:"^6.21.0"},{id:"tencent-cos",name:"\u817E\u8BAF\u4E91 COS",region:"cn",envVars:["TENCENT_COS_SECRET_ID","TENCENT_COS_SECRET_KEY","TENCENT_COS_BUCKET","TENCENT_COS_REGION"],docs:"https://cloud.tencent.com/document/product/436",pkg:"cos-nodejs-sdk-v5",pkgVersion:"^2.13.7"},{id:"qiniu",name:"\u4E03\u725B\u4E91 Kodo",region:"cn",envVars:["QINIU_ACCESS_KEY","QINIU_SECRET_KEY","QINIU_BUCKET","QINIU_DOMAIN"],docs:"https://developer.qiniu.com/kodo",pkg:"qiniu",pkgVersion:"^7.14.0"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function yn(e){let t=e==="supabase"?"supabase-storage":e;return It.some(o=>o.id===t)?t:void 0}function lr(e){let t=yn(e);return t?It.find(o=>o.id===t):void 0}var ud=It.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Ve="@nebutra/storage";function Sn(e,t){je.mkdirSync(Fe.dirname(e),{recursive:!0}),je.writeFileSync(e,t)}function Fa(e,t){let o=Fe.join(e,".env.example");je.existsSync(o)?je.appendFileSync(o,`
2400
- `+t):je.writeFileSync(o,t)}function ja(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2398
+ `}function Ga(e){switch(e){case"twilio":return Va();case"messagebird":return Ba();case"plivo":return Ka();case"aliyun-sms":return $a();case"tencent-sms":return Ya();case"yunpian":return qa();case"none":return`export {};
2399
+ `}}function Ha(e){let t={};for(let n of e.pkgs??[]){let r=Ma[n];r&&(t[n]=r)}let o={name:Ua,version:"0.1.0",private:!0,description:`Transactional SMS via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(o,null,2)+`
2400
+ `}async function fr(e,t,o="global"){if(t==="none")return;let n=gr(t);if(!n)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${Jt.map(i=>i.id).join(", ")}`);let r=De.join(e,"packages","sms");if(!Ee.existsSync(r))return;let s=De.join(r,"src");Ee.existsSync(s)&&Ee.rmSync(s,{recursive:!0,force:!0});try{yn(De.join(r,"package.json"),Ha(n)),yn(De.join(s,"types.ts"),ja),yn(De.join(s,"index.ts"),Ga(n.id)),Da(e,Fa(n))}catch(i){throw console.error(`Failed to apply SMS selection "${t}":`,i),new Error(`SMS scaffold for "${t}" failed \u2014 see stderr for details.`)}}import je from"fs";import Fe from"path";var wt=[{id:"r2",name:"Cloudflare R2",region:"global",envVars:["R2_ACCOUNT_ID","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY","R2_BUCKET"],docs:"https://developers.cloudflare.com/r2/api/s3/api/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"s3",name:"AWS S3",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_S3_REGION","S3_BUCKET"],docs:"https://docs.aws.amazon.com/s3/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"supabase-storage",name:"Supabase Storage",region:"global",envVars:["SUPABASE_URL","SUPABASE_SERVICE_ROLE_KEY","SUPABASE_BUCKET"],docs:"https://supabase.com/docs/guides/storage",pkg:"@supabase/supabase-js",pkgVersion:"^2.45.4"},{id:"aliyun-oss",name:"\u963F\u91CC\u4E91 OSS",region:"cn",envVars:["ALIYUN_OSS_ACCESS_KEY","ALIYUN_OSS_ACCESS_SECRET","ALIYUN_OSS_REGION","ALIYUN_OSS_BUCKET"],docs:"https://help.aliyun.com/product/31815.html",pkg:"ali-oss",pkgVersion:"^6.21.0"},{id:"tencent-cos",name:"\u817E\u8BAF\u4E91 COS",region:"cn",envVars:["TENCENT_COS_SECRET_ID","TENCENT_COS_SECRET_KEY","TENCENT_COS_BUCKET","TENCENT_COS_REGION"],docs:"https://cloud.tencent.com/document/product/436",pkg:"cos-nodejs-sdk-v5",pkgVersion:"^2.13.7"},{id:"qiniu",name:"\u4E03\u725B\u4E91 Kodo",region:"cn",envVars:["QINIU_ACCESS_KEY","QINIU_SECRET_KEY","QINIU_BUCKET","QINIU_DOMAIN"],docs:"https://developer.qiniu.com/kodo",pkg:"qiniu",pkgVersion:"^7.14.0"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function Sn(e){let t=e==="supabase"?"supabase-storage":e;return wt.some(o=>o.id===t)?t:void 0}function yr(e){let t=Sn(e);return t?wt.find(o=>o.id===t):void 0}var kd=wt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Ve="@nebutra/storage";function hn(e,t){je.mkdirSync(Fe.dirname(e),{recursive:!0}),je.writeFileSync(e,t)}function Wa(e,t){let o=Fe.join(e,".env.example");je.existsSync(o)?je.appendFileSync(o,`
2401
+ `+t):je.writeFileSync(o,t)}function Xa(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2401
2402
  `);return`${t}
2402
2403
  ${o}
2403
- `}var Va=`/**
2404
+ `}var za=`/**
2404
2405
  * Inputs for the \`uploadFile\` wrapper. Keep this surface portable across
2405
2406
  * providers \u2014 provider-specific options belong in the wrapper itself.
2406
2407
  */
@@ -2426,7 +2427,7 @@ export interface SignedUrlOptions {
2426
2427
  operation?: "get" | "put";
2427
2428
  contentType?: string;
2428
2429
  }
2429
- `;function Ba(){return`/**
2430
+ `;function Ja(){return`/**
2430
2431
  * @${Ve.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
2431
2432
  *
2432
2433
  * Docs: https://developers.cloudflare.com/r2/api/s3/api/
@@ -2490,7 +2491,7 @@ export async function getSignedUrl(
2490
2491
  }
2491
2492
 
2492
2493
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2493
- `}function Ka(){return`/**
2494
+ `}function Qa(){return`/**
2494
2495
  * @${Ve.slice(1)} \u2014 AWS S3 wrapper.
2495
2496
  *
2496
2497
  * Docs: https://docs.aws.amazon.com/s3/
@@ -2555,7 +2556,7 @@ export async function getSignedUrl(
2555
2556
  }
2556
2557
 
2557
2558
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2558
- `}function $a(){return`/**
2559
+ `}function Za(){return`/**
2559
2560
  * @${Ve.slice(1)} \u2014 Supabase Storage wrapper.
2560
2561
  *
2561
2562
  * Docs: https://supabase.com/docs/guides/storage
@@ -2618,7 +2619,7 @@ export async function getSignedUrl(
2618
2619
  }
2619
2620
 
2620
2621
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2621
- `}function Ya(){return`/**
2622
+ `}function ec(){return`/**
2622
2623
  * @${Ve.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2623
2624
  *
2624
2625
  * Docs: https://help.aliyun.com/product/31815.html
@@ -2665,7 +2666,7 @@ export async function getSignedUrl(
2665
2666
  }
2666
2667
 
2667
2668
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2668
- `}function qa(){return`/**
2669
+ `}function tc(){return`/**
2669
2670
  * @${Ve.slice(1)} \u2014 \u817E\u8BAF\u4E91 COS wrapper via cos-nodejs-sdk-v5.
2670
2671
  *
2671
2672
  * Docs: https://cloud.tencent.com/document/product/436
@@ -2720,7 +2721,7 @@ export async function getSignedUrl(
2720
2721
  }
2721
2722
 
2722
2723
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2723
- `}function Ga(){return`/**
2724
+ `}function nc(){return`/**
2724
2725
  * @${Ve.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2725
2726
  *
2726
2727
  * Docs: https://developer.qiniu.com/kodo
@@ -2788,9 +2789,9 @@ export async function getSignedUrl(
2788
2789
  }
2789
2790
 
2790
2791
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2791
- `}function Ha(e){switch(e){case"r2":return Ba();case"s3":return Ka();case"supabase-storage":return $a();case"aliyun-oss":return Ya();case"tencent-cos":return qa();case"qiniu":return Ga();case"none":return`export {};
2792
- `}}function Wa(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),(e.id==="r2"||e.id==="s3")&&(t["@aws-sdk/s3-request-presigner"]="^3.658.0");let o={name:Ve,version:"0.1.0",private:!0,description:`Object storage via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(o,null,2)+`
2793
- `}async function dr(e,t,o){if(t==="none")return;let n=lr(t);if(!n)throw new Error(`Unknown storage provider "${t}". Valid ids: ${It.map(i=>i.id).join(", ")}`);let r=Fe.join(e,"packages","storage"),s=Fe.join(r,"src");je.existsSync(s)&&je.rmSync(s,{recursive:!0,force:!0}),Sn(Fe.join(r,"package.json"),Wa(n)),Sn(Fe.join(s,"types.ts"),Va),Sn(Fe.join(s,"index.ts"),Ha(n.id)),Fa(e,ja(n))}function ve(e,t){if(e===void 0)return t;let o=String(e).trim().toLowerCase();return o==="true"||o==="1"||o==="yes"||o==="on"?!0:o==="false"||o==="0"||o==="no"||o==="off"?!1:t}function ur(e,t){let o=t==="cn";return{cronJobs:ve(e.cronJobs,!0),auditLog:ve(e.auditLog,!0),apiKeys:ve(e.apiKeys,!0),webhooks:ve(e.webhooks,!0),commandPalette:ve(e.commandPalette,!0),cookieConsent:ve(e.cookieConsent,!0),legalPages:ve(e.legalPages,!0),chinaCompliance:ve(e.chinaCompliance,o)}}var Jt=[{id:"svix",name:"Svix",region:"global",envVars:["SVIX_API_TOKEN"],docs:"https://docs.svix.com",description:"Managed webhooks platform"},{id:"custom",name:"Custom (self-hosted)",region:"both",envVars:["WEBHOOK_SIGNING_SECRET"],docs:"",description:"Custom implementation with built-in package"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function mr(e){return Jt.find(t=>t.id===e)}var Ed=Jt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function gr(e,t,o="global"){let n=mr(t);if(!n)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Jt.map(r=>r.id).join(", ")}`);if(n.id==="none"){X(e,"webhooks");return}n.envVars.length>0&&te(e,{category:"Webhooks",name:n.name,envVars:n.envVars,docs:n.docs}),ne(e,"WEBHOOKS_PROVIDER",n.id)}import Be from"fs";import wt from"path";function Xa(e){return`import Link from "next/link";
2792
+ `}function oc(e){switch(e){case"r2":return Ja();case"s3":return Qa();case"supabase-storage":return Za();case"aliyun-oss":return ec();case"tencent-cos":return tc();case"qiniu":return nc();case"none":return`export {};
2793
+ `}}function rc(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),(e.id==="r2"||e.id==="s3")&&(t["@aws-sdk/s3-request-presigner"]="^3.658.0");let o={name:Ve,version:"0.1.0",private:!0,description:`Object storage via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(o,null,2)+`
2794
+ `}async function Sr(e,t,o){if(t==="none")return;let n=yr(t);if(!n)throw new Error(`Unknown storage provider "${t}". Valid ids: ${wt.map(i=>i.id).join(", ")}`);let r=Fe.join(e,"packages","storage"),s=Fe.join(r,"src");je.existsSync(s)&&je.rmSync(s,{recursive:!0,force:!0}),hn(Fe.join(r,"package.json"),rc(n)),hn(Fe.join(s,"types.ts"),za),hn(Fe.join(s,"index.ts"),oc(n.id)),Wa(e,Xa(n))}function ve(e,t){if(e===void 0)return t;let o=String(e).trim().toLowerCase();return o==="true"||o==="1"||o==="yes"||o==="on"?!0:o==="false"||o==="0"||o==="no"||o==="off"?!1:t}function hr(e,t){let o=t==="cn";return{cronJobs:ve(e.cronJobs,!0),auditLog:ve(e.auditLog,!0),apiKeys:ve(e.apiKeys,!0),webhooks:ve(e.webhooks,!0),commandPalette:ve(e.commandPalette,!0),cookieConsent:ve(e.cookieConsent,!0),legalPages:ve(e.legalPages,!0),chinaCompliance:ve(e.chinaCompliance,o)}}var Qt=[{id:"svix",name:"Svix",region:"global",envVars:["SVIX_API_TOKEN"],docs:"https://docs.svix.com",description:"Managed webhooks platform"},{id:"custom",name:"Custom (self-hosted)",region:"both",envVars:["WEBHOOK_SIGNING_SECRET"],docs:"",description:"Custom implementation with built-in package"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Er(e){return Qt.find(t=>t.id===e)}var Md=Qt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function vr(e,t,o="global"){let n=Er(t);if(!n)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Qt.map(r=>r.id).join(", ")}`);if(n.id==="none"){X(e,"webhooks");return}n.envVars.length>0&&te(e,{category:"Webhooks",name:n.name,envVars:n.envVars,docs:n.docs}),ne(e,"WEBHOOKS_PROVIDER",n.id)}import Be from"fs";import Rt from"path";function sc(e){return`import Link from "next/link";
2794
2795
 
2795
2796
  export default function WelcomePage() {
2796
2797
  const projectName = ${JSON.stringify(e)};
@@ -2899,12 +2900,12 @@ function Step({
2899
2900
  </li>
2900
2901
  );
2901
2902
  }
2902
- `}function za(e={}){return`
2903
+ `}function ic(e={}){return`
2903
2904
  ## What you can do next
2904
2905
 
2905
2906
  ${[e.apiKeys===!1?"- Manage API keys at `/settings/api-keys` (disabled \u2014 re-enable with `--api-keys=true`)":"- Manage API keys at `/settings/api-keys`",e.auditLog===!1?"- View audit log at `/settings/audit-log` (disabled \u2014 re-enable with `--audit-log=true`)":"- View audit log at `/settings/audit-log`","- Configure webhooks at `/settings/webhooks`",e.commandPalette===!1?"- Press \u2318K to open the command palette (disabled \u2014 re-enable with `--command-palette=true`)":"- Press \u2318K to open the command palette","- Edit notification preferences at `/settings/notifications`","- Export your data at `/settings/account/export`","- For China deployments, see `packages/ops/china-compliance/README.md`"].join(`
2906
2907
  `)}
2907
- `}function Ja(e=[]){return e.length===0?"":`
2908
+ `}function ac(e=[]){return e.length===0?"":`
2908
2909
  ## Production readiness holds
2909
2910
 
2910
2911
  Do not enable these in production until you replace stubs, add provider credentials, and verify the integration contract:
@@ -2913,7 +2914,7 @@ ${e.map(o=>{let n=rt(o.status);return`- ${o.flag}=${o.provider} ${n} \u2014 ${me
2913
2914
  `)}
2914
2915
 
2915
2916
  Review the package readiness matrix before handoff: [docs/package-status.md](docs/package-status.md)
2916
- `}function Qa(e,t,o=[],n={}){return`# Next steps \u2014 ${e}
2917
+ `}function cc(e,t,o=[],n={}){return`# Next steps \u2014 ${e}
2917
2918
 
2918
2919
  Region: ${t}
2919
2920
 
@@ -2939,17 +2940,17 @@ Your AI-native SaaS scaffold is ready. Complete these four steps to go from temp
2939
2940
  \`\`\`
2940
2941
 
2941
2942
  After setup, delete the welcome route at \`apps/web/src/app/[locale]/welcome/\`.
2942
- ${za(n)}${Ja(o)}
2943
+ ${ic(n)}${ac(o)}
2943
2944
 
2944
2945
  ## Resources
2945
2946
 
2946
2947
  - [Documentation](/docs)
2947
2948
  - [GitHub](https://github.com/nebutra/nebutra-sailor)
2948
2949
  - [Get free license (Individual/OPC)](https://nebutra.com/get-license)
2949
- `}async function fr(e,t){let{projectName:o,region:n,previewSelections:r=[],waveFeatures:s={}}=t;try{let i=wt.join(e,".sailor");Be.existsSync(i)||Be.mkdirSync(i,{recursive:!0}),Be.writeFileSync(wt.join(i,"next-steps.md"),Qa(o,n,r,s))}catch(i){let c=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write .sailor/next-steps.md: ${c}`)}try{let i=wt.join(e,"apps","web");if(!Be.existsSync(i))return;let c=wt.join(i,"src","app","[locale]","welcome");Be.existsSync(c)||Be.mkdirSync(c,{recursive:!0}),Be.writeFileSync(wt.join(c,"page.tsx"),Xa(o))}catch(i){let c=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write welcome page: ${c}`)}}var yr="create-sailor";function p(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2950
- `)}function tc(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function Sr(e){switch(e){case"postgres":case"postgresql":return"postgresql";case"mysql":return"mysql";case"sqlite":return"sqlite";case"none":return"none";default:return"postgresql"}}function hr(e,t,o){let n=e?.trim().toLowerCase()??Gn(t),r=Kt(n);if(!r){let i=sn.map(c=>c.id).join(", ");throw new Error(`Unknown --db-host="${n}". Valid: ${i}`)}let s=o;return r.forcedEngine&&s!=="none"&&s!==r.forcedEngine&&(s=r.forcedEngine),{hostId:r.id,engine:s}}function Er(e){return e==="drizzle"?"drizzle":"prisma"}function vr(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function _r(e){if(!e)return"stripe";let t=e.toLowerCase();return t==="lemon"||t==="lemonsqueezy"?"lemon":t==="wechat"?"wechat":t==="alipay"?"alipay":t==="none"?"none":"stripe"}function br(e){if(!e)return"clerk";let t=e.toLowerCase();return t==="betterauth"||t==="better-auth"?"betterauth":t==="nextauth"||t==="next-auth"||t==="authjs"||t==="auth.js"?"nextauth":t==="supabase"||t==="supabase-auth"?"supabase":t==="none"?"none":"clerk"}var nc=new Set(["gateway","direct","custom","none"]);function kr(e){if(!e)return!1;let t=e.trim().toLowerCase();return nc.has(t)}function Pr(e){if(!e)return["openai"];if(kr(e))return[];let t=e.split(",").map(o=>o.trim().toLowerCase());return t.includes("none")?[]:t}function oc(e,t){let o=e??t;return yn(o)??o}var Ar={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function Cr(e,t){if(!e)return"fumadocs";let o=e.toLowerCase();if(o==="fumadocs"||o==="none")return o;if(o in Ar){let n=Ar[o];return t?p(!0,{event:"notice",kind:"docs-fallback",requested:o,effective:"fumadocs"}):process.stdout.write(A.yellow(`\u26A0 ${n} support is coming in v1.2. Falling back to fumadocs.
2950
+ `}async function _r(e,t){let{projectName:o,region:n,previewSelections:r=[],waveFeatures:s={}}=t;try{let i=Rt.join(e,".sailor");Be.existsSync(i)||Be.mkdirSync(i,{recursive:!0}),Be.writeFileSync(Rt.join(i,"next-steps.md"),cc(o,n,r,s))}catch(i){let c=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write .sailor/next-steps.md: ${c}`)}try{let i=Rt.join(e,"apps","web");if(!Be.existsSync(i))return;let c=Rt.join(i,"src","app","[locale]","welcome");Be.existsSync(c)||Be.mkdirSync(c,{recursive:!0}),Be.writeFileSync(Rt.join(c,"page.tsx"),sc(o))}catch(i){let c=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write welcome page: ${c}`)}}var br="create-sailor";function p(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2951
+ `)}function dc(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function Pr(e){switch(e){case"postgres":case"postgresql":return"postgresql";case"mysql":return"mysql";case"sqlite":return"sqlite";case"none":return"none";default:return"postgresql"}}function Ar(e,t,o){let n=e?.trim().toLowerCase()??Hn(t),r=$t(n);if(!r){let i=an.map(c=>c.id).join(", ");throw new Error(`Unknown --db-host="${n}". Valid: ${i}`)}let s=o;return r.forcedEngine&&s!=="none"&&s!==r.forcedEngine&&(s=r.forcedEngine),{hostId:r.id,engine:s}}function Cr(e){return e==="drizzle"?"drizzle":"prisma"}function Ir(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function wr(e){if(!e)return"stripe";let t=e.toLowerCase();return t==="lemon"||t==="lemonsqueezy"?"lemon":t==="wechat"?"wechat":t==="alipay"?"alipay":t==="none"?"none":"stripe"}function Rr(e){if(!e)return"clerk";let t=e.toLowerCase();return t==="betterauth"||t==="better-auth"?"betterauth":t==="nextauth"||t==="next-auth"||t==="authjs"||t==="auth.js"?"nextauth":t==="supabase"||t==="supabase-auth"?"supabase":t==="none"?"none":"clerk"}var uc=new Set(["gateway","direct","custom","none"]);function Ur(e){if(!e)return!1;let t=e.trim().toLowerCase();return uc.has(t)}function kr(e){if(!e)return["openai"];if(Ur(e))return[];let t=e.split(",").map(o=>o.trim().toLowerCase());return t.includes("none")?[]:t}function mc(e,t){let o=e??t;return Sn(o)??o}var xr={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function Nr(e,t){if(!e)return"fumadocs";let o=e.toLowerCase();if(o==="fumadocs"||o==="none")return o;if(o in xr){let n=xr[o];return t?p(!0,{event:"notice",kind:"docs-fallback",requested:o,effective:"fumadocs"}):process.stdout.write(A.yellow(`\u26A0 ${n} support is coming in v1.2. Falling back to fumadocs.
2951
2952
  `)+A.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
2952
- `)),"fumadocs"}return"fumadocs"}function Ir(e){switch(e){case"vercel":return"vercel";case"railway":return"railway";case"cloudflare":return"cloudflare";case"selfhost":return"selfhost";case"none":return"none";default:return"vercel"}}function wr(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function rc(e){return{...e==="cn"?{email:"aliyun-dm",storage:"aliyun-oss",monitoring:"sentry",analytics:"baidu",sms:"aliyun-sms"}:e==="hybrid"?{email:"resend",storage:"aliyun-oss",monitoring:"sentry",analytics:"posthog",sms:"aliyun-sms"}:{email:"resend",storage:"r2",monitoring:"sentry",analytics:"posthog",sms:"twilio"},queue:"none",search:"none",cache:e==="global"?"upstash-redis":e==="cn"?"redis":"upstash-redis",notifications:"none",webhooks:"none",cms:"none",featureFlags:"none",captcha:e==="cn"?"aliyun-slide":"turnstile",mcp:"on",metering:"auto",billingMode:"usage",idp:"clerk",accessGate:"none"}}function Rr(e){return e==="cn"?"wechat":"stripe"}async function sc(){let e=new Za;e.name(yr).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(ae,"-v, --version").helpOption(!1).argument("[name]","project directory",void 0).option("-p, --pm <id>","npm | pnpm | yarn | bun").option("--region <id>","global | cn | hybrid").option("--orm <id>","prisma (default, primary) | drizzle (dual-ORM: adds db-drizzle alongside Prisma \u2014 Postgres only)").option("--db <id>","postgres | mysql | sqlite | none \u2014 engine (Prisma provider)").option("--db-host <id>","local | supabase | neon | vercel-postgres | planetscale | railway | aliyun-rds | tencent-cdb | none \u2014 managed-provider (region default: supabase global, local cn)").option("--auth <id>","clerk | betterauth | nextauth | supabase | none").option("--social-login <ids>","CN social login providers \u2014 wechat | qq | dingtalk | workweixin | feishu | weibo (comma-separated)").option("--payment <id>","stripe | lemon | wechat | alipay | none").option("--ai <mode-or-ids>","topology shorthand (gateway | direct | custom | none) OR comma-separated provider ids (e.g. openai,anthropic)").option("--deploy <target>","vercel | railway | cloudflare | selfhost").option("--docs <id>","fumadocs | mintlify | docusaurus | nextra | vitepress | none").option("--email <id>","resend | postmark | ses | aliyun-dm | tencent-ses | netease | none").option("--storage <id>","r2 | s3 | supabase-storage | aliyun-oss | tencent-cos | qiniu | none").option("--monitoring <id>","sentry | datadog | aliyun-arms | tingyun | none").option("--analytics <id>","posthog | plausible | umami | baidu | sensors | none").option("--sms <id>","twilio | aliyun-sms | tencent-sms | yunpian | none").option("--queue <id>","qstash | bullmq | sqs | none").option("--search <id>","meilisearch | typesense | algolia | pgvector | none").option("--cache <id>","upstash-redis | vercel-kv | redis | dragonfly | none").option("--notifications <id>","novu | knock | custom | none").option("--webhooks <id>","svix | custom | none").option("--cms <id>","sanity | contentful | strapi | none").option("--feature-flags <id>","vercel-flags | growthbook | configcat | none").option("--captcha <id>","turnstile | hcaptcha | aliyun-slide | none").option("--mcp <mode>","on | off (default: on)").option("--metering <mode>","auto | on | off (default: auto \u2014 auto-on when payment is set)").option("--billing-mode <mode>","usage | seat | credits (default: usage)").option("--idp <id>","clerk | oauth-server (default: clerk)").option("--access-gate <mode>","none | invite (default: none)").option("--cron-jobs <bool>","true | false \u2014 scaffold scheduled cron handlers (default: true)").option("--audit-log <bool>","true | false \u2014 enable /settings/audit-log + arch test (default: true)").option("--api-keys <bool>","true | false \u2014 enable /settings/api-keys page (default: true)").option("--command-palette <bool>","true | false \u2014 enable \u2318K command palette (default: true)").option("--cookie-consent <bool>","true | false \u2014 enable GDPR/CCPA cookie banner (default: true)").option("--legal-pages <bool>","true | false \u2014 enable dynamic /legal/[slug] route (default: true)").option("--china-compliance <bool>","true | false \u2014 enable @nebutra/china-compliance + ICP footer (default: true when --region=cn, otherwise false)").option("--i18n","enable i18n").option("--no-i18n","disable i18n").option("--with-workflows","scaffold workflows/ (inngest + n8n + pusher stubs)").option("--with-python-backend","scaffold backends/python/ (FastAPI stub \u2014 only when TS-by-Default ADR exception applies)").option("--no-install","skip package install").option("--no-git","skip git init").option("-y, --yes","accept all defaults (non-interactive)").option("--dry-run","preview actions without writing files").option("--json","machine-readable output").option("--no-color","disable color output").option("-h, --help","show help"),e.parse(process.argv);let t=e.opts(),[o]=e.args;t.help&&(An(),process.exit(0));let n=!!t.json,r=!!t.dryRun,s=!!t.yes,i=s||!process.stdin.isTTY;if(n||_n(),p(n,{event:"start",version:ae}),!t.pm)try{Rt("pnpm --version",{stdio:"ignore"})}catch{n||process.stderr.write(`
2953
+ `)),"fumadocs"}return"fumadocs"}function Tr(e){switch(e){case"vercel":return"vercel";case"railway":return"railway";case"cloudflare":return"cloudflare";case"selfhost":return"selfhost";case"none":return"none";default:return"vercel"}}function Or(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function gc(e){return{...e==="cn"?{email:"aliyun-dm",storage:"aliyun-oss",monitoring:"sentry",analytics:"baidu",sms:"aliyun-sms"}:e==="hybrid"?{email:"resend",storage:"aliyun-oss",monitoring:"sentry",analytics:"posthog",sms:"aliyun-sms"}:{email:"resend",storage:"r2",monitoring:"sentry",analytics:"posthog",sms:"twilio"},queue:"none",search:"none",cache:e==="global"?"upstash-redis":e==="cn"?"redis":"upstash-redis",notifications:"none",webhooks:"none",cms:"none",featureFlags:"none",captcha:e==="cn"?"aliyun-slide":"turnstile",mcp:"on",metering:"auto",billingMode:"usage",idp:"clerk",accessGate:"none"}}function Lr(e){return e==="cn"?"wechat":"stripe"}async function fc(){let e=new pc;e.name(br).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(ae,"-v, --version").helpOption(!1).argument("[name]","project directory",void 0).option("-p, --pm <id>","npm | pnpm | yarn | bun").option("--region <id>","global | cn | hybrid").option("--orm <id>","prisma (default, primary) | drizzle (dual-ORM: adds db-drizzle alongside Prisma \u2014 Postgres only)").option("--db <id>","postgres | mysql | sqlite | none \u2014 engine (Prisma provider)").option("--db-host <id>","local | supabase | neon | vercel-postgres | planetscale | railway | aliyun-rds | tencent-cdb | none \u2014 managed-provider (region default: supabase global, local cn)").option("--auth <id>","clerk | betterauth | nextauth | supabase | none").option("--social-login <ids>","CN social login providers \u2014 wechat | qq | dingtalk | workweixin | feishu | weibo (comma-separated)").option("--payment <id>","stripe | lemon | wechat | alipay | none").option("--ai <mode-or-ids>","topology shorthand (gateway | direct | custom | none) OR comma-separated provider ids (e.g. openai,anthropic)").option("--deploy <target>","vercel | railway | cloudflare | selfhost").option("--docs <id>","fumadocs | mintlify | docusaurus | nextra | vitepress | none").option("--email <id>","resend | postmark | ses | aliyun-dm | tencent-ses | netease | none").option("--storage <id>","r2 | s3 | supabase-storage | aliyun-oss | tencent-cos | qiniu | none").option("--monitoring <id>","sentry | datadog | aliyun-arms | tingyun | none").option("--analytics <id>","posthog | plausible | umami | baidu | sensors | none").option("--sms <id>","twilio | aliyun-sms | tencent-sms | yunpian | none").option("--queue <id>","qstash | bullmq | sqs | none").option("--search <id>","meilisearch | typesense | algolia | pgvector | none").option("--cache <id>","upstash-redis | vercel-kv | redis | dragonfly | none").option("--notifications <id>","novu | knock | custom | none").option("--webhooks <id>","svix | custom | none").option("--cms <id>","sanity | contentful | strapi | none").option("--feature-flags <id>","vercel-flags | growthbook | configcat | none").option("--captcha <id>","turnstile | hcaptcha | aliyun-slide | none").option("--mcp <mode>","on | off (default: on)").option("--metering <mode>","auto | on | off (default: auto \u2014 auto-on when payment is set)").option("--billing-mode <mode>","usage | seat | credits (default: usage)").option("--idp <id>","clerk | oauth-server (default: clerk)").option("--access-gate <mode>","none | invite (default: none)").option("--cron-jobs <bool>","true | false \u2014 scaffold scheduled cron handlers (default: true)").option("--audit-log <bool>","true | false \u2014 enable /settings/audit-log + arch test (default: true)").option("--api-keys <bool>","true | false \u2014 enable /settings/api-keys page (default: true)").option("--command-palette <bool>","true | false \u2014 enable \u2318K command palette (default: true)").option("--cookie-consent <bool>","true | false \u2014 enable GDPR/CCPA cookie banner (default: true)").option("--legal-pages <bool>","true | false \u2014 enable dynamic /legal/[slug] route (default: true)").option("--china-compliance <bool>","true | false \u2014 enable @nebutra/china-compliance + ICP footer (default: true when --region=cn, otherwise false)").option("--i18n","enable i18n").option("--no-i18n","disable i18n").option("--with-workflows","scaffold workflows/ (inngest + n8n + pusher stubs)").option("--with-python-backend","scaffold backends/python/ (FastAPI stub \u2014 only when TS-by-Default ADR exception applies)").option("--no-install","skip package install").option("--no-git","skip git init").option("-y, --yes","accept all defaults (non-interactive)").option("--dry-run","preview actions without writing files").option("--json","machine-readable output").option("--no-color","disable color output").option("-h, --help","show help"),e.parse(process.argv);let t=e.opts(),[o]=e.args;t.help&&(Cn(),process.exit(0));let n=!!t.json,r=!!t.dryRun,s=!!t.yes,i=s||!process.stdin.isTTY;if(n||(ho(),bn()),p(n,{event:"start",version:ae}),!t.pm)try{kt("pnpm --version",{stdio:"ignore"})}catch{n||process.stderr.write(`
2953
2954
  ${A.red("\u2718")} ${A.bold("pnpm is required")} but was not found on PATH.
2954
2955
 
2955
2956
  The scaffold uses pnpm workspaces + Turborepo. Install pnpm first:
@@ -2959,24 +2960,24 @@ Then retry: ${A.cyan("pnpm dlx create-sailor@latest")}
2959
2960
  (or pass ${A.dim("--pm=npm")} if you know workspace:* won't resolve in your setup)
2960
2961
 
2961
2962
  `),p(n,{event:"error",code:"PNPM_MISSING"}),process.exit(1)}let c=o??(s?"./my-saas-app":void 0),a;if(c)a=c;else if(i)a="./my-saas-app";else{let g=await O.group({name:()=>O.text({message:"Where should we create your project?",placeholder:"./my-saas-app",defaultValue:"./my-saas-app",validate:h=>{if(h.length===0)return"Please enter a path."}})},{onCancel:()=>{process.stdout.write(A.red(`\u2718 Cancelled
2962
- `)),process.exit(130)}});a=String(g.name)}let l=de.basename(de.resolve(a)),d=t.pm??tc(),S=!!t.region,C=!!t.auth,k=!!t.payment,$=!!t.ai,ue=!!t.email,b=!!t.storage,m=!!t.monitoring,U=!!t.analytics,kt=!!t.sms,hn=t.i18n!==void 0,E,Ke,G,xt="local",mt,H,F,Q=On(t.socialLogin),gt,Qt,be,$e,ie,W,Nt;if(i){E=wr(t.region),Ke=Er(t.orm);{let Ae=Sr(t.db),j=hr(t.dbHost,E,Ae);G=j.engine,xt=j.hostId}let g=k?t.payment:Rr(E);mt=vr(g),H=_r(g),F=br(t.auth);let h="gateway";if($){let Ae=t.ai?.trim().toLowerCase()??"";kr(Ae)?h=Ae:h="direct"}let L=nn({mode:h,providerIds:$?Pr(t.ai):void 0});gt=L.mode,Qt=L.routing,be=L.providerIds,ie=Ir(t.deploy),W=Cr(t.docs,n),Nt=hn?!!t.i18n:!0}else{let g={};S||(g.region=()=>O.select({message:"Target region?",options:[{value:"global",label:"global \u2014 \u6D77\u5916\u4F18\u5148"},{value:"cn",label:"cn \u2014 \u56FD\u5185\u4F18\u5148"},{value:"hybrid",label:"hybrid \u2014 \u53CC\u8F68\uFF08\u56FD\u5185+\u51FA\u6D77\uFF09"}],initialValue:"global"})),C||(g.auth=()=>O.select({message:"Auth provider?",options:[{value:"clerk",label:"Clerk",hint:"managed, fastest setup"},{value:"betterauth",label:"Better Auth",hint:"self-hosted, modern (2FA / passkeys / RBAC)"},{value:"nextauth",label:"NextAuth (Auth.js v5)",hint:"self-hosted, mature, large ecosystem"},{value:"supabase",label:"Supabase Auth",hint:"managed auth with Supabase storage/realtime ecosystem"},{value:"none",label:"None"}],initialValue:"clerk"})),$||(g.aiMode=()=>O.select({message:"AI topology?",options:[{value:"gateway",label:"Multi-provider AI Gateway / router",hint:"recommended"},{value:"direct",label:"Direct SDK/provider adapters"},{value:"custom",label:"OpenAI-compatible endpoint"},{value:"none",label:"Skip AI"}],initialValue:"gateway"}),g.aiProviders=({results:f})=>{if(f.aiMode!=="direct")return Promise.resolve([]);let _=tn.map(Y=>({value:Y.id,label:`[${Y.category}] ${Y.name}`}));return O.multiselect({message:"Select direct AI provider adapters (expert path)",options:_,initialValues:["openai"],required:!1})},g.customAiName=({results:f})=>f.aiMode==="custom"?O.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),g.customAiBaseUrl=({results:f})=>f.aiMode==="custom"?O.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:_=>{if(_.length===0)return"Base URL is required."}}):Promise.resolve(void 0),g.customAiApiKeyEnv=({results:f})=>f.aiMode==="custom"?O.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0));let h=Object.keys(g).length>0?await O.group(g,{onCancel:()=>{process.stdout.write(A.red(`\u2718 Cancelled
2963
- `)),process.exit(130)}}):{};E=wr(S?t.region:h.region),Ke=Er(t.orm);{let f=Sr(t.db),_=hr(t.dbHost,E,f);G=_.engine,xt=_.hostId}let L=k?t.payment:Rr(E);mt=vr(L),H=_r(L),F=br(C?t.auth:h.auth);let Ae=h.aiMode==="custom"?{name:h.customAiName??"custom",baseURL:h.customAiBaseUrl??"",apiKeyEnvName:h.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,j=nn({mode:$?t.ai?.trim().toLowerCase()==="none"?"none":"direct":h.aiMode??"gateway",providerIds:$?Pr(t.ai):h.aiProviders,customEndpoint:Ae});gt=j.mode,Qt=j.routing,be=j.providerIds,j.customEndpoint&&($e={name:j.customEndpoint.name,baseURL:j.customEndpoint.baseURL,apiKeyEnvName:j.customEndpoint.apiKeyEnvName}),ie=Ir(t.deploy),W=Cr(t.docs,n),Nt=hn?!!t.i18n:!0}let R=rc(E),Ye=ue?t.email:R.email,qe=oc(b?t.storage:void 0,R.storage),Ge=m?t.monitoring:R.monitoring,He=U?t.analytics:R.analytics,We=kt?t.sms:R.sms,Xe=t.queue??R.queue,ze=t.search??R.search,ft=t.cache??R.cache,Je=t.notifications??R.notifications,Qe=t.webhooks??R.webhooks,yt=t.cms??R.cms,Ze=t.featureFlags??R.featureFlags,et=t.captcha??R.captcha,Tt=t.mcp??R.mcp,St=t.metering??R.metering,tt=t.billingMode??R.billingMode,nt=t.idp??R.idp,ht=t.accessGate==="invite"?"invite":R.accessGate,I=ur({cronJobs:t.cronJobs,auditLog:t.auditLog,apiKeys:t.apiKeys,commandPalette:t.commandPalette,cookieConsent:t.cookieConsent,legalPages:t.legalPages,chinaCompliance:t.chinaCompliance},E),ot=bn([{flag:"queue",provider:Xe},{flag:"search",provider:ze},{flag:"notifications",provider:Je},{flag:"webhooks",provider:Qe},{flag:"feature-flags",provider:Ze},{flag:"captcha",provider:et},{flag:"access-gate",provider:ht}]);function Zt(){for(let g of ot)if(n)p(!0,{event:"warn",step:g.flag,provider:g.provider,packageStatus:g.status,message:me(g.status)});else{let h=rt(g.status);process.stdout.write(A.yellow(`\u26A0 ${g.flag}=${g.provider} ${h} \u2014 ${me(g.status)}
2964
- `))}}let Pe={region:E,orm:Ke,database:G,payment:mt,aiMode:gt,aiRouting:Qt,aiProviders:be,customAiEndpoint:$e,deployTarget:ie,docs:W,i18n:Nt,email:Ye,storage:qe,monitoring:Ge,analytics:He,sms:We,queue:Xe,search:ze,cache:ft,notifications:Je,webhooks:Qe,cms:yt,featureFlags:Ze,captcha:et,mcp:Tt,metering:St,billingMode:tt,idp:nt,accessGate:ht,cronJobs:I.cronJobs,auditLog:I.auditLog,apiKeys:I.apiKeys,commandPalette:I.commandPalette,cookieConsent:I.cookieConsent,legalPages:I.legalPages,chinaCompliance:I.chinaCompliance},Ot=[["Project name",l],["Region",E],["Auth",F],["Social login",Q.length>0?Q.map(g=>Et.find(h=>h.id===g)?.name??g).join(", "):"none"],["ORM",Ke],["Database",G],["Payment",H],["AI topology",`${gt}${be.length>0?` (${be.join(", ")} seed)`:""}${$e?" + custom endpoint":""}`],["Email",Ye],["Storage",qe],["Monitoring",Ge],["Analytics",He],["SMS",We],["Deploy Target",ie],["Docs Framework",W],["Access gate",ht]];n?Ot.forEach(([g,h],L)=>{p(!0,{event:"step",step:g,value:h,index:L+1,total:Ot.length})}):Ot.forEach(([g,h],L)=>{In({index:L+1,total:Ot.length,label:g,value:h})});let xr={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""},En=Date.now();if(r){let g=be.length,h=[`clone template \u2192 ${a}`,"write nebutra.config.json",`prune template (orm=${Ke}, i18n=${Nt})`,`region \u2192 ${E}`,`auth \u2192 ${F==="none"?"skip (remove packages/auth)":`configure ${F}`}`,...Q.length>0?[`social-login \u2192 generate ${Q.length} callback route${Q.length===1?"":"s"} + SocialLoginButtons.tsx (${Q.join(", ")})`]:[],`db \u2192 ${G==="none"?"skip (remove packages/db)":`configure Prisma for ${G}`}`,`payment \u2192 ${H==="none"?"skip (remove packages/billing)":`configure ${H}`}`,...W!=="none"?[`docs \u2192 scaffold apps/docs (${W==="fumadocs"?"fumadocs":`${W} \u2192 fumadocs fallback`})`]:[],...g>0||$e?[`ai-providers \u2192 generate ${gt} registry seed + env (${g}${$e?" + custom":""} provider${g===1&&!$e?"":"s"})`]:[],...Ye!=="none"?[`email \u2192 configure ${Ye}`]:[],...qe!=="none"?[`storage \u2192 configure ${qe}`]:[],...Ge!=="none"?[`monitoring \u2192 configure ${Ge}`]:[],...He!=="none"?[`analytics \u2192 configure ${He}`]:[],...We!=="none"?[`sms \u2192 configure ${We}`]:[],...Xe!=="none"?[`queue \u2192 configure ${Xe}`]:[],...ze!=="none"?[`search \u2192 configure ${ze}`]:[],...ft!=="none"?[`cache \u2192 configure ${ft}`]:[],...Je!=="none"?[`notifications \u2192 configure ${Je}`]:[],...Qe!=="none"?[`webhooks \u2192 configure ${Qe}`]:[],...yt!=="none"?[`cms \u2192 configure ${yt}`]:[],...Ze!=="none"?[`feature-flags \u2192 configure ${Ze}`]:[],...et!=="none"?[`captcha \u2192 configure ${et}`]:[],`mcp \u2192 ${Tt==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${St==="off"?"disabled":St==="auto"?mt!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...tt!=="usage"?[`billing-mode \u2192 ${tt}`]:[],...nt!=="clerk"?[`idp \u2192 ${nt}`]:[],`cron-jobs \u2192 ${I.cronJobs?"enabled":"disabled"}`,`audit-log \u2192 ${I.auditLog?"enabled":"disabled"}`,`api-keys \u2192 ${I.apiKeys?"enabled":"disabled"}`,`command-palette \u2192 ${I.commandPalette?"enabled":"disabled"}`,`cookie-consent \u2192 ${I.cookieConsent?"enabled":"disabled"}`,`legal-pages \u2192 ${I.legalPages?"enabled":"disabled"}`,`china-compliance \u2192 ${I.chinaCompliance?"enabled (@nebutra/china-compliance + ICP footer)":"disabled"}`,`compliance \u2192 inject ${E} boilerplate (ICP/Cookie/AIGC/Privacy)`,"welcome \u2192 generate dev welcome page","env \u2192 generate random secrets (AUTH_SECRET, JWT_SECRET)","seed \u2192 generate prisma/seed.ts (1 admin + 3 tenants)",...ie!=="none"?[`deploy \u2192 inject ${ie} config`]:[],"inject .env.local",t.install===!1?"skip install":`run ${d} install`,t.git===!1?"skip git init":"run git init"];if(n){for(let L of h)p(!0,{event:"plan",action:L});Zt(),p(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2963
+ `)),process.exit(130)}});a=String(g.name)}let l=de.basename(de.resolve(a)),u=t.pm??dc(),S=!!t.region,I=!!t.auth,C=!!t.payment,U=!!t.ai,ue=!!t.email,b=!!t.storage,m=!!t.monitoring,M=!!t.analytics,xt=!!t.sms,En=t.i18n!==void 0,E,Ke,G,Nt="local",mt,H,j,Q=Ln(t.socialLogin),gt,Zt,be,$e,ie,W,Tt;if(i){E=Or(t.region),Ke=Cr(t.orm);{let Ae=Pr(t.db),V=Ar(t.dbHost,E,Ae);G=V.engine,Nt=V.hostId}let g=C?t.payment:Lr(E);mt=Ir(g),H=wr(g),j=Rr(t.auth);let h="gateway";if(U){let Ae=t.ai?.trim().toLowerCase()??"";Ur(Ae)?h=Ae:h="direct"}let L=on({mode:h,providerIds:U?kr(t.ai):void 0});gt=L.mode,Zt=L.routing,be=L.providerIds,ie=Tr(t.deploy),W=Nr(t.docs,n),Tt=En?!!t.i18n:!0}else{let g={};S||(g.region=()=>O.select({message:"Target region?",options:[{value:"global",label:"global \u2014 \u6D77\u5916\u4F18\u5148"},{value:"cn",label:"cn \u2014 \u56FD\u5185\u4F18\u5148"},{value:"hybrid",label:"hybrid \u2014 \u53CC\u8F68\uFF08\u56FD\u5185+\u51FA\u6D77\uFF09"}],initialValue:"global"})),I||(g.auth=()=>O.select({message:"Auth provider?",options:[{value:"clerk",label:"Clerk",hint:"managed, fastest setup"},{value:"betterauth",label:"Better Auth",hint:"self-hosted, modern (2FA / passkeys / RBAC)"},{value:"nextauth",label:"NextAuth (Auth.js v5)",hint:"self-hosted, mature, large ecosystem"},{value:"supabase",label:"Supabase Auth",hint:"managed auth with Supabase storage/realtime ecosystem"},{value:"none",label:"None"}],initialValue:"clerk"})),U||(g.aiMode=()=>O.select({message:"AI topology?",options:[{value:"gateway",label:"Multi-provider AI Gateway / router",hint:"recommended"},{value:"direct",label:"Direct SDK/provider adapters"},{value:"custom",label:"OpenAI-compatible endpoint"},{value:"none",label:"Skip AI"}],initialValue:"gateway"}),g.aiProviders=({results:f})=>{if(f.aiMode!=="direct")return Promise.resolve([]);let _=nn.map(Y=>({value:Y.id,label:`[${Y.category}] ${Y.name}`}));return O.multiselect({message:"Select direct AI provider adapters (expert path)",options:_,initialValues:["openai"],required:!1})},g.customAiName=({results:f})=>f.aiMode==="custom"?O.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),g.customAiBaseUrl=({results:f})=>f.aiMode==="custom"?O.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:_=>{if(_.length===0)return"Base URL is required."}}):Promise.resolve(void 0),g.customAiApiKeyEnv=({results:f})=>f.aiMode==="custom"?O.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0));let h=Object.keys(g).length>0?await O.group(g,{onCancel:()=>{process.stdout.write(A.red(`\u2718 Cancelled
2964
+ `)),process.exit(130)}}):{};E=Or(S?t.region:h.region),Ke=Cr(t.orm);{let f=Pr(t.db),_=Ar(t.dbHost,E,f);G=_.engine,Nt=_.hostId}let L=C?t.payment:Lr(E);mt=Ir(L),H=wr(L),j=Rr(I?t.auth:h.auth);let Ae=h.aiMode==="custom"?{name:h.customAiName??"custom",baseURL:h.customAiBaseUrl??"",apiKeyEnvName:h.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,V=on({mode:U?t.ai?.trim().toLowerCase()==="none"?"none":"direct":h.aiMode??"gateway",providerIds:U?kr(t.ai):h.aiProviders,customEndpoint:Ae});gt=V.mode,Zt=V.routing,be=V.providerIds,V.customEndpoint&&($e={name:V.customEndpoint.name,baseURL:V.customEndpoint.baseURL,apiKeyEnvName:V.customEndpoint.apiKeyEnvName}),ie=Tr(t.deploy),W=Nr(t.docs,n),Tt=En?!!t.i18n:!0}let k=gc(E),Ye=ue?t.email:k.email,qe=mc(b?t.storage:void 0,k.storage),Ge=m?t.monitoring:k.monitoring,He=M?t.analytics:k.analytics,We=xt?t.sms:k.sms,Xe=t.queue??k.queue,ze=t.search??k.search,ft=t.cache??k.cache,Je=t.notifications??k.notifications,Qe=t.webhooks??k.webhooks,yt=t.cms??k.cms,Ze=t.featureFlags??k.featureFlags,et=t.captcha??k.captcha,Ot=t.mcp??k.mcp,St=t.metering??k.metering,tt=t.billingMode??k.billingMode,nt=t.idp??k.idp,ht=t.accessGate==="invite"?"invite":k.accessGate,w=hr({cronJobs:t.cronJobs,auditLog:t.auditLog,apiKeys:t.apiKeys,commandPalette:t.commandPalette,cookieConsent:t.cookieConsent,legalPages:t.legalPages,chinaCompliance:t.chinaCompliance},E),ot=Pn([{flag:"queue",provider:Xe},{flag:"search",provider:ze},{flag:"notifications",provider:Je},{flag:"webhooks",provider:Qe},{flag:"feature-flags",provider:Ze},{flag:"captcha",provider:et},{flag:"access-gate",provider:ht}]);function en(){for(let g of ot)if(n)p(!0,{event:"warn",step:g.flag,provider:g.provider,packageStatus:g.status,message:me(g.status)});else{let h=rt(g.status);process.stdout.write(A.yellow(`\u26A0 ${g.flag}=${g.provider} ${h} \u2014 ${me(g.status)}
2965
+ `))}}let Pe={region:E,orm:Ke,database:G,payment:mt,aiMode:gt,aiRouting:Zt,aiProviders:be,customAiEndpoint:$e,deployTarget:ie,docs:W,i18n:Tt,email:Ye,storage:qe,monitoring:Ge,analytics:He,sms:We,queue:Xe,search:ze,cache:ft,notifications:Je,webhooks:Qe,cms:yt,featureFlags:Ze,captcha:et,mcp:Ot,metering:St,billingMode:tt,idp:nt,accessGate:ht,cronJobs:w.cronJobs,auditLog:w.auditLog,apiKeys:w.apiKeys,commandPalette:w.commandPalette,cookieConsent:w.cookieConsent,legalPages:w.legalPages,chinaCompliance:w.chinaCompliance},Lt=[["Project name",l],["Region",E],["Auth",j],["Social login",Q.length>0?Q.map(g=>Et.find(h=>h.id===g)?.name??g).join(", "):"none"],["ORM",Ke],["Database",G],["Payment",H],["AI topology",`${gt}${be.length>0?` (${be.join(", ")} seed)`:""}${$e?" + custom endpoint":""}`],["Email",Ye],["Storage",qe],["Monitoring",Ge],["Analytics",He],["SMS",We],["Deploy Target",ie],["Docs Framework",W],["Access gate",ht]];n?Lt.forEach(([g,h],L)=>{p(!0,{event:"step",step:g,value:h,index:L+1,total:Lt.length})}):Lt.forEach(([g,h],L)=>{wn({index:L+1,total:Lt.length,label:g,value:h})});let Mr={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""},vn=Date.now();if(r){let g=be.length,h=[`clone template \u2192 ${a}`,"write nebutra.config.json",`prune template (orm=${Ke}, i18n=${Tt})`,`region \u2192 ${E}`,`auth \u2192 ${j==="none"?"skip (remove packages/auth)":`configure ${j}`}`,...Q.length>0?[`social-login \u2192 generate ${Q.length} callback route${Q.length===1?"":"s"} + SocialLoginButtons.tsx (${Q.join(", ")})`]:[],`db \u2192 ${G==="none"?"skip (remove packages/db)":`configure Prisma for ${G}`}`,`payment \u2192 ${H==="none"?"skip (remove packages/billing)":`configure ${H}`}`,...W!=="none"?[`docs \u2192 scaffold apps/docs (${W==="fumadocs"?"fumadocs":`${W} \u2192 fumadocs fallback`})`]:[],...g>0||$e?[`ai-providers \u2192 generate ${gt} registry seed + env (${g}${$e?" + custom":""} provider${g===1&&!$e?"":"s"})`]:[],...Ye!=="none"?[`email \u2192 configure ${Ye}`]:[],...qe!=="none"?[`storage \u2192 configure ${qe}`]:[],...Ge!=="none"?[`monitoring \u2192 configure ${Ge}`]:[],...He!=="none"?[`analytics \u2192 configure ${He}`]:[],...We!=="none"?[`sms \u2192 configure ${We}`]:[],...Xe!=="none"?[`queue \u2192 configure ${Xe}`]:[],...ze!=="none"?[`search \u2192 configure ${ze}`]:[],...ft!=="none"?[`cache \u2192 configure ${ft}`]:[],...Je!=="none"?[`notifications \u2192 configure ${Je}`]:[],...Qe!=="none"?[`webhooks \u2192 configure ${Qe}`]:[],...yt!=="none"?[`cms \u2192 configure ${yt}`]:[],...Ze!=="none"?[`feature-flags \u2192 configure ${Ze}`]:[],...et!=="none"?[`captcha \u2192 configure ${et}`]:[],`mcp \u2192 ${Ot==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${St==="off"?"disabled":St==="auto"?mt!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...tt!=="usage"?[`billing-mode \u2192 ${tt}`]:[],...nt!=="clerk"?[`idp \u2192 ${nt}`]:[],`cron-jobs \u2192 ${w.cronJobs?"enabled":"disabled"}`,`audit-log \u2192 ${w.auditLog?"enabled":"disabled"}`,`api-keys \u2192 ${w.apiKeys?"enabled":"disabled"}`,`command-palette \u2192 ${w.commandPalette?"enabled":"disabled"}`,`cookie-consent \u2192 ${w.cookieConsent?"enabled":"disabled"}`,`legal-pages \u2192 ${w.legalPages?"enabled":"disabled"}`,`china-compliance \u2192 ${w.chinaCompliance?"enabled (@nebutra/china-compliance + ICP footer)":"disabled"}`,`compliance \u2192 inject ${E} boilerplate (ICP/Cookie/AIGC/Privacy)`,"welcome \u2192 generate dev welcome page","env \u2192 generate random secrets (AUTH_SECRET, JWT_SECRET)","seed \u2192 generate prisma/seed.ts (1 admin + 3 tenants)",...ie!=="none"?[`deploy \u2192 inject ${ie} config`]:[],"inject .env.local",t.install===!1?"skip install":`run ${u} install`,t.git===!1?"skip git init":"run git init"];if(n){for(let L of h)p(!0,{event:"plan",action:L});en(),p(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2965
2966
  `+A.bold(`Dry run \u2014 planned actions:
2966
2967
  `));for(let L of h)process.stdout.write(` \u2022 ${L}
2967
2968
  `);ot.length>0&&(process.stdout.write(`
2968
2969
  `+A.bold(A.yellow(`Preview-status providers selected:
2969
- `))),Zt()),process.stdout.write(A.dim(`
2970
+ `))),en()),process.stdout.write(A.dim(`
2970
2971
  No files were written.
2971
- `))}process.exit(0)}let Nr=async()=>{process.stdout.write(`
2972
+ `))}process.exit(0)}let Dr=async()=>{process.stdout.write(`
2972
2973
  `+A.red(`\u2718 Cancelled
2973
2974
  `)),_e.existsSync(a)&&await O.confirm({message:`Cleanup partial install at ${a}?`,initialValue:!0})===!0&&(_e.rmSync(a,{recursive:!0,force:!0}),process.stdout.write(A.dim(` \u2713 Removed ${a}
2974
- `))),process.exit(130)};process.on("SIGINT",Nr);try{p(n,{event:"step",step:"clone",status:"start"}),await vo(a),p(n,{event:"step",step:"clone",status:"ok"}),p(n,{event:"step",step:"package",status:"start"}),await Oo(a,l),p(n,{event:"step",step:"package",status:"ok"}),p(n,{event:"step",step:"config",status:"start"}),await qn(a,Pe),p(n,{event:"step",step:"config",status:"ok"}),p(n,{event:"step",step:"prune",status:"start"}),await qo(a,Pe),p(n,{event:"step",step:"prune",status:"ok"});let g=de.join(a,"packages/platform/db/prisma/schema.prisma");if(_e.existsSync(g)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let f=_e.readFileSync(g,"utf-8"),_={auth:F,payment:H,"billing-mode":tt,idp:nt,template:"saas","access-gate":ht},Y=gn(f,_);_e.writeFileSync(g,Y),mn(de.join(de.dirname(g),"migrations"),_),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(f){let _=f instanceof Error?f.message:String(f);p(n,{event:"step",step:"schema-prune",status:"error",error:_})}}else p(n,{event:"step",step:"schema-prune",status:"skip"});if(p(n,{event:"step",step:"auth",choice:F,status:"start"}),await Nn(a,F),p(n,{event:"step",step:"auth",choice:F,status:"ok"}),Q.length>0?(p(n,{event:"step",step:"social-login",providers:Q,status:"start"}),await Un(a,Q,F),p(n,{event:"step",step:"social-login",providers:Q,status:"ok"})):p(n,{event:"step",step:"social-login",status:"skip"}),p(n,{event:"step",step:"db",choice:G,status:"start"}),await Xn(a,G,l),G!=="none"){let f=Kt(xt);f&&(await zn(a,f,l),p(n,{event:"step",step:"db-host",choice:xt,status:"ok"}))}if(p(n,{event:"step",step:"db",choice:G,status:"ok"}),Ke==="drizzle"){p(n,{event:"step",step:"orm",choice:"drizzle",status:"start"});let f=await Mo(a,"drizzle",G);p(n,{event:"step",step:"orm",choice:"drizzle",status:f.applied?"ok":"skip",...f.reason?{reason:f.reason}:{}})}if(p(n,{event:"step",step:"payment",choice:H,status:"start"}),await Fo(a,H),p(n,{event:"step",step:"payment",choice:H,status:"ok"}),await so(a,Ye,E),n&&p(!0,{event:"step",step:"email",choice:Ye,status:"ok"}),await dr(a,qe,E),n&&p(!0,{event:"step",step:"storage",choice:qe,status:"ok"}),await xo(a,Ge,E),n&&p(!0,{event:"step",step:"monitoring",choice:Ge,status:"ok"}),await kn(a,He,E),n&&p(!0,{event:"step",step:"analytics",choice:He,status:"ok"}),await pr(a,We,E),n&&p(!0,{event:"step",step:"sms",choice:We,status:"ok"}),await Qo(a,Xe,E),n&&p(!0,{event:"step",step:"queue",choice:Xe,status:"ok"}),await ir(a,ze,E),n&&p(!0,{event:"step",step:"search",choice:ze,status:"ok"}),await jn(a,ft,E),n&&p(!0,{event:"step",step:"cache",choice:ft,status:"ok"}),await To(a,Je,E),n&&p(!0,{event:"step",step:"notifications",choice:Je,status:"ok"}),await gr(a,Qe,E),n&&p(!0,{event:"step",step:"webhooks",choice:Qe,status:"ok"}),await $n(a,yt,E),n&&p(!0,{event:"step",step:"cms",choice:yt,status:"ok"}),await mo(a,Ze,E),n&&p(!0,{event:"step",step:"feature-flags",choice:Ze,status:"ok"}),await Bn(a,et,E),n&&p(!0,{event:"step",step:"captcha",choice:et,status:"ok"}),await Co(a,Tt),n&&p(!0,{event:"step",step:"mcp",mode:Tt,status:"ok"}),await wo(a,St,mt),n&&p(!0,{event:"step",step:"metering",mode:St,status:"ok"}),p(n,{event:"step",step:"prune-wave-features",status:"start"}),Go(a,I),p(n,{event:"step",step:"prune-wave-features",status:"ok",toggles:I}),Pe.orm==="prisma"&&Pe.database!=="none"){let f=de.join(a,"packages/platform/db/prisma/schema.prisma");if(_e.existsSync(f)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let _=_e.readFileSync(f,"utf8"),Y={auth:F,payment:H,"billing-mode":tt,idp:nt,template:"saas","access-gate":ht},Tr=gn(_,Y);_e.writeFileSync(f,Tr),mn(de.join(de.dirname(f),"migrations"),Y),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(_){let Y=_ instanceof Error?_.message:String(_);p(n,{event:"step",step:"schema-prune",status:"error",error:Y})}}else p(n,{event:"step",step:"schema-prune",status:"skip"})}else p(n,{event:"step",step:"schema-prune",status:"skip"});if(p(n,{event:"step",step:"billing-mode",choice:tt,status:"ok"}),p(n,{event:"step",step:"idp",choice:nt,status:"ok"}),await Yn(a,E),n&&p(!0,{event:"step",step:"compliance",region:E,status:"ok"}),await lo(a),await ar(a,F),await fr(a,{projectName:l,region:E,previewSelections:ot,waveFeatures:I}),Pe.aiMode!=="none"){p(n,{event:"step",step:"ai-providers",status:"start"});let f={providerIds:Pe.aiProviders,customEndpoint:Pe.customAiEndpoint},_=de.join(a,"packages/ai/ai-providers/templates");await $o(a,f,_),p(n,{event:"step",step:"ai-providers",status:"ok"})}else p(n,{event:"step",step:"ai-providers",status:"skip"});p(n,{event:"step",step:"docs",status:"start"}),W!=="none"?(await to(a,{framework:W,projectName:l}),p(n,{event:"step",step:"docs",framework:"fumadocs",requested:W,status:"ok"})):p(n,{event:"step",step:"docs",status:"skip"}),p(n,{event:"step",step:"deploy-target",status:"start"}),ie!=="none"&&await Qn(a,ie),p(n,{event:"step",step:"deploy-target",status:"ok"}),p(n,{event:"step",step:"env",status:"start"}),await ao(a,xr),p(n,{event:"step",step:"env",status:"ok"}),p(n,{event:"step",step:"scaffold-extras",status:"start"});let h=await er(a,{projectName:l,withWorkflows:!!t.withWorkflows,withPythonBackend:!!t.withPythonBackend});p(n,{event:"step",step:"scaffold-extras",status:"ok",applied:h.applied,skipped:h.skipped}),p(n,{event:"step",step:"license",status:"start"});try{let f=Ao(a,{projectName:l,cliVersion:ae});p(n,{event:"step",step:"license",status:"ok",tier:"independent",wrote:f.wrote}),n||process.stdout.write(A.dim(` License: Nebutra-Sailor Independent Developer License (free for \u2264 1 FTE, < $1M ARR).
2975
+ `))),process.exit(130)};process.on("SIGINT",Dr);try{p(n,{event:"step",step:"clone",status:"start"}),await Co(a),p(n,{event:"step",step:"clone",status:"ok"}),p(n,{event:"step",step:"package",status:"start"}),await jo(a,l),p(n,{event:"step",step:"package",status:"ok"}),p(n,{event:"step",step:"config",status:"start"}),await Gn(a,Pe),p(n,{event:"step",step:"config",status:"ok"}),p(n,{event:"step",step:"prune",status:"start"}),await Jo(a,Pe),p(n,{event:"step",step:"prune",status:"ok"});let g=de.join(a,"packages/platform/db/prisma/schema.prisma");if(_e.existsSync(g)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let f=_e.readFileSync(g,"utf-8"),_={auth:j,payment:H,"billing-mode":tt,idp:nt,template:"saas","access-gate":ht},Y=fn(f,_);_e.writeFileSync(g,Y),gn(de.join(de.dirname(g),"migrations"),_),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(f){let _=f instanceof Error?f.message:String(f);p(n,{event:"step",step:"schema-prune",status:"error",error:_})}}else p(n,{event:"step",step:"schema-prune",status:"skip"});if(p(n,{event:"step",step:"auth",choice:j,status:"start"}),await Tn(a,j),p(n,{event:"step",step:"auth",choice:j,status:"ok"}),Q.length>0?(p(n,{event:"step",step:"social-login",providers:Q,status:"start"}),await Mn(a,Q,j),p(n,{event:"step",step:"social-login",providers:Q,status:"ok"})):p(n,{event:"step",step:"social-login",status:"skip"}),p(n,{event:"step",step:"db",choice:G,status:"start"}),await zn(a,G,l),G!=="none"){let f=$t(Nt);f&&(await Jn(a,f,l),p(n,{event:"step",step:"db-host",choice:Nt,status:"ok"}))}if(p(n,{event:"step",step:"db",choice:G,status:"ok"}),Ke==="drizzle"){p(n,{event:"step",step:"orm",choice:"drizzle",status:"start"});let f=await Ko(a,"drizzle",G);p(n,{event:"step",step:"orm",choice:"drizzle",status:f.applied?"ok":"skip",...f.reason?{reason:f.reason}:{}})}if(p(n,{event:"step",step:"payment",choice:H,status:"start"}),await Yo(a,H),p(n,{event:"step",step:"payment",choice:H,status:"ok"}),await io(a,Ye,E),n&&p(!0,{event:"step",step:"email",choice:Ye,status:"ok"}),await Sr(a,qe,E),n&&p(!0,{event:"step",step:"storage",choice:qe,status:"ok"}),await Mo(a,Ge,E),n&&p(!0,{event:"step",step:"monitoring",choice:Ge,status:"ok"}),await xn(a,He,E),n&&p(!0,{event:"step",step:"analytics",choice:He,status:"ok"}),await fr(a,We,E),n&&p(!0,{event:"step",step:"sms",choice:We,status:"ok"}),await rr(a,Xe,E),n&&p(!0,{event:"step",step:"queue",choice:Xe,status:"ok"}),await ur(a,ze,E),n&&p(!0,{event:"step",step:"search",choice:ze,status:"ok"}),await Vn(a,ft,E),n&&p(!0,{event:"step",step:"cache",choice:ft,status:"ok"}),await Fo(a,Je,E),n&&p(!0,{event:"step",step:"notifications",choice:Je,status:"ok"}),await vr(a,Qe,E),n&&p(!0,{event:"step",step:"webhooks",choice:Qe,status:"ok"}),await Yn(a,yt,E),n&&p(!0,{event:"step",step:"cms",choice:yt,status:"ok"}),await go(a,Ze,E),n&&p(!0,{event:"step",step:"feature-flags",choice:Ze,status:"ok"}),await Kn(a,et,E),n&&p(!0,{event:"step",step:"captcha",choice:et,status:"ok"}),await No(a,Ot),n&&p(!0,{event:"step",step:"mcp",mode:Ot,status:"ok"}),await Oo(a,St,mt),n&&p(!0,{event:"step",step:"metering",mode:St,status:"ok"}),p(n,{event:"step",step:"prune-wave-features",status:"start"}),Qo(a,w),p(n,{event:"step",step:"prune-wave-features",status:"ok",toggles:w}),Pe.orm==="prisma"&&Pe.database!=="none"){let f=de.join(a,"packages/platform/db/prisma/schema.prisma");if(_e.existsSync(f)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let _=_e.readFileSync(f,"utf8"),Y={auth:j,payment:H,"billing-mode":tt,idp:nt,template:"saas","access-gate":ht},Fr=fn(_,Y);_e.writeFileSync(f,Fr),gn(de.join(de.dirname(f),"migrations"),Y),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(_){let Y=_ instanceof Error?_.message:String(_);p(n,{event:"step",step:"schema-prune",status:"error",error:Y})}}else p(n,{event:"step",step:"schema-prune",status:"skip"})}else p(n,{event:"step",step:"schema-prune",status:"skip"});if(p(n,{event:"step",step:"billing-mode",choice:tt,status:"ok"}),p(n,{event:"step",step:"idp",choice:nt,status:"ok"}),await qn(a,E),n&&p(!0,{event:"step",step:"compliance",region:E,status:"ok"}),await uo(a),await mr(a,j),await _r(a,{projectName:l,region:E,previewSelections:ot,waveFeatures:w}),Pe.aiMode!=="none"){p(n,{event:"step",step:"ai-providers",status:"start"});let f={providerIds:Pe.aiProviders,customEndpoint:Pe.customAiEndpoint},_=de.join(a,"packages/ai/ai-providers/templates");await Xo(a,f,_),p(n,{event:"step",step:"ai-providers",status:"ok"})}else p(n,{event:"step",step:"ai-providers",status:"skip"});p(n,{event:"step",step:"docs",status:"start"}),W!=="none"?(await no(a,{framework:W,projectName:l}),p(n,{event:"step",step:"docs",framework:"fumadocs",requested:W,status:"ok"})):p(n,{event:"step",step:"docs",status:"skip"}),p(n,{event:"step",step:"deploy-target",status:"start"}),ie!=="none"&&await Zn(a,ie),p(n,{event:"step",step:"deploy-target",status:"ok"}),p(n,{event:"step",step:"env",status:"start"}),await co(a,Mr),p(n,{event:"step",step:"env",status:"ok"}),p(n,{event:"step",step:"scaffold-extras",status:"start"});let h=await ir(a,{projectName:l,withWorkflows:!!t.withWorkflows,withPythonBackend:!!t.withPythonBackend});p(n,{event:"step",step:"scaffold-extras",status:"ok",applied:h.applied,skipped:h.skipped}),p(n,{event:"step",step:"license",status:"start"});try{let f=xo(a,{projectName:l,cliVersion:ae});p(n,{event:"step",step:"license",status:"ok",tier:"independent",wrote:f.wrote}),n||process.stdout.write(A.dim(` License: Nebutra-Sailor Independent Developer License (free for \u2264 1 FTE, < $1M ARR).
2975
2976
  Upstream AGPL preserved as LICENSE-AGPL-REFERENCE.md.
2976
- `))}catch(f){p(n,{event:"step",step:"license",status:"warn",message:f instanceof Error?f.message:String(f)})}if(t.install!==!1){let f=d==="bun"?"bun install":`${d} install`;n?p(!0,{event:"step",step:"install",pm:d,status:"start"}):process.stdout.write(A.dim(` Installing dependencies with ${d}\u2026
2977
- `));try{Rt(f,{cwd:a,stdio:n?"ignore":"inherit"}),p(n,{event:"step",step:"install",status:"ok"})}catch(_){let Y=_ instanceof Error?_.message:String(_);n?p(!0,{event:"step",step:"install",status:"error",error:Y}):process.stdout.write(A.yellow(` \u26A0 install failed \u2014 run '${f}' manually.
2978
- `))}}else p(n,{event:"step",step:"install",status:"skip"});if(t.git!==!1){n&&p(!0,{event:"step",step:"git-init",status:"start"});try{Rt("git init -q",{cwd:a,stdio:"ignore"}),Rt("git add -A",{cwd:a,stdio:"ignore"}),Rt('git -c user.email=you@example.com -c user.name="You" commit -q -m "chore: initial scaffold from create-sailor"',{cwd:a,stdio:"ignore"}),p(n,{event:"step",step:"git-init",status:"ok"})}catch(f){let _=f instanceof Error?f.message:String(f);n?p(!0,{event:"step",step:"git-init",status:"error",error:_}):process.stdout.write(A.yellow(` \u26A0 git init skipped \u2014 not fatal.
2979
- `))}}else p(n,{event:"step",step:"git-init",status:"skip"});let j=Math.max(1,Math.round((Date.now()-En)/1e3));xn({template_version:ae,package_manager:d,region:E,auth:F,payment:H,ai_providers:be,deploy_target:ie,duration_ms:Date.now()-En}),ot.length>0&&Zt(),n?p(!0,{event:"done",status:"ok",elapsedSec:j,targetDir:a,previewSelections:ot,waveFeatures:I}):Pn({elapsedSec:j,targetDir:a,skippedInstall:t.install===!1,previewSelections:ot,waveFeatures:I});try{ec({pkg:{name:yr,version:ae},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}process.exit(0)}catch(g){let h=g instanceof Error?g.message:String(g);n?p(!0,{event:"error",message:h}):process.stdout.write(A.red(`
2977
+ `))}catch(f){p(n,{event:"step",step:"license",status:"warn",message:f instanceof Error?f.message:String(f)})}if(t.install!==!1){let f=u==="bun"?"bun install":`${u} install`;n?p(!0,{event:"step",step:"install",pm:u,status:"start"}):process.stdout.write(A.dim(` Installing dependencies with ${u}\u2026
2978
+ `));try{kt(f,{cwd:a,stdio:n?"ignore":"inherit"}),p(n,{event:"step",step:"install",status:"ok"})}catch(_){let Y=_ instanceof Error?_.message:String(_);n?p(!0,{event:"step",step:"install",status:"error",error:Y}):process.stdout.write(A.yellow(` \u26A0 install failed \u2014 run '${f}' manually.
2979
+ `))}}else p(n,{event:"step",step:"install",status:"skip"});if(t.git!==!1){n&&p(!0,{event:"step",step:"git-init",status:"start"});try{kt("git init -q",{cwd:a,stdio:"ignore"}),kt("git add -A",{cwd:a,stdio:"ignore"}),kt('git -c user.email=you@example.com -c user.name="You" commit -q -m "chore: initial scaffold from create-sailor"',{cwd:a,stdio:"ignore"}),p(n,{event:"step",step:"git-init",status:"ok"})}catch(f){let _=f instanceof Error?f.message:String(f);n?p(!0,{event:"step",step:"git-init",status:"error",error:_}):process.stdout.write(A.yellow(` \u26A0 git init skipped \u2014 not fatal.
2980
+ `))}}else p(n,{event:"step",step:"git-init",status:"skip"});let V=Math.max(1,Math.round((Date.now()-vn)/1e3));Nn({template_version:ae,package_manager:u,region:E,auth:j,payment:H,ai_providers:be,deploy_target:ie,duration_ms:Date.now()-vn}),ot.length>0&&en(),n?p(!0,{event:"done",status:"ok",elapsedSec:V,targetDir:a,previewSelections:ot,waveFeatures:w}):An({elapsedSec:V,targetDir:a,skippedInstall:t.install===!1,previewSelections:ot,waveFeatures:w});try{lc({pkg:{name:br,version:ae},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}process.exit(0)}catch(g){let h=g instanceof Error?g.message:String(g);n?p(!0,{event:"error",message:h}):process.stdout.write(A.red(`
2980
2981
  \u2718 Failed: ${h}
2981
- `)),process.exit(1)}}sc().catch(e=>{process.stderr.write(String(e)+`
2982
+ `)),process.exit(1)}}fc().catch(e=>{process.stderr.write(String(e)+`
2982
2983
  `),process.exit(1)});