create-sailor 1.4.4 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import{execSync as Et}from"child_process";import fe from"fs";import vt from"path";import*as x from"@clack/prompts";import{Command as ua}from"commander";import C from"picocolors";import ma from"update-notifier";import ur from"cfonts";import mr from"picocolors";import dn from"fs";import Yt from"path";import{fileURLToPath as lr}from"url";function dr(){try{let t=Yt.dirname(lr(import.meta.url));for(let o=0;o<4;o++){let n=Yt.join(t,"package.json");if(dn.existsSync(n)){let r=dn.readFileSync(n,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=Yt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var ae=dr();function un(){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 vt}from"child_process";import fe from"fs";import _t from"path";import*as x from"@clack/prompts";import{Command as va}from"commander";import C from"picocolors";import _a from"update-notifier";import Sr from"cfonts";import hr from"picocolors";import mn from"fs";import Gt from"path";import{fileURLToPath as fr}from"url";function yr(){try{let t=Gt.dirname(fr(import.meta.url));for(let o=0;o<4;o++){let n=Gt.join(t,"package.json");if(mn.existsSync(n)){let r=mn.readFileSync(n,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=Gt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var ae=yr();function gn(){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}Sr.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(hr.dim(` AI-Native SaaS Template \xB7 v${ae} \xB7 nebutra.com
4
4
 
5
- `))}import P from"picocolors";var gr={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"};function fr(e){return e?gr[e]??"stable":"stable"}function Je(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function ce(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 mn(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 yr(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function gn(e){let t=yr(),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 N=t?P.bold(P.yellow("\u26A0 Preview features selected:")):"!! Preview features selected:";c.push("",` ${N}`);for(let T of a){let D=Je(T.status),ie=` ${n} ${T.flag} (${T.provider}) ${D}`;c.push(t?P.yellow(ie):ie)}c.push("",` ${t?P.dim(ce("foundation")):ce("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??{},m=N=>N!==!1,S=[];m(l.apiKeys)&&S.push("Manage API keys at /settings/api-keys"),m(l.auditLog)&&S.push("View audit log at /settings/audit-log"),S.push("Configure webhooks at /settings/webhooks"),m(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 N of S)c.push(` ${n} ${N}`);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 Er={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"};function vr(e){return e?Er[e]??"stable":"stable"}function Qe(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function ce(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 fn(e){let t=[];for(let{flag:o,provider:n}of e){if(!n||n==="none")continue;let r=vr(n);r!=="stable"&&t.push({flag:o,provider:n,status:r})}return t}function _r(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function yn(e){let t=_r(),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 T=t?P.bold(P.yellow("\u26A0 Preview features selected:")):"!! Preview features selected:";c.push("",` ${T}`);for(let N of a){let D=Qe(N.status),ie=` ${n} ${N.flag} (${N.provider}) ${D}`;c.push(t?P.yellow(ie):ie)}c.push("",` ${t?P.dim(ce("foundation")):ce("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??{},m=T=>T!==!1,S=[];m(l.apiKeys)&&S.push("Manage API keys at /settings/api-keys"),m(l.auditLog)&&S.push("View audit log at /settings/audit-log"),S.push("Configure webhooks at /settings/webhooks"),m(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 T of S)c.push(` ${n} ${T}`);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 Sr=`Usage: create-sailor [name] [options]
7
+ `)}var br=`Usage: create-sailor [name] [options]
8
8
 
9
9
  Arguments:
10
10
  name project directory (default: ./my-saas-app)
@@ -73,9 +73,9 @@ Examples:
73
73
  $ npx create-sailor@latest my-app --region=cn --auth=clerk
74
74
  $ npx create-sailor@latest my-app --region=hybrid --ai=openai,deepseek
75
75
  $ npm create sailor@latest --dry-run --region=cn
76
- `;function fn(){process.stdout.write(Sr)}import At from"picocolors";function yn(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function hr(e){let t=yn()?"\u25B8":"->",o=`[${e.index}/${e.total}]`,n=e.label.padEnd(18," ");return yn()?`${At.dim(o)} ${At.bold(n)} ${At.dim(t)} ${At.cyan(e.value)}`:`${o} ${n} ${t} ${e.value}`}function Sn(e){process.stdout.write(hr(e)+`
77
- `)}var qt=[{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:[]}],Ua=qt.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var Er=["openai","anthropic","google"],vr=["openai"];function Gt(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let o=t.length>0?t:[...Er];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:[...vr];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 Qe from"fs";import j from"path";var hn=[{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:""}],Da=hn.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function En(e){return hn.find(t=>t.id===e)}function _r(e){Qe.mkdirSync(e,{recursive:!0})}function z(e,t){_r(j.dirname(e)),Qe.writeFileSync(e,t)}function he(e,t){let o=j.join(e,".env.example");Qe.existsSync(o)?Qe.appendFileSync(o,`
78
- `+t):Qe.writeFileSync(o,t)}function br(e){let t=`"use client";
76
+ `;function Sn(){process.stdout.write(br)}import wt from"picocolors";function hn(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Pr(e){let t=hn()?"\u25B8":"->",o=`[${e.index}/${e.total}]`,n=e.label.padEnd(18," ");return hn()?`${wt.dim(o)} ${wt.bold(n)} ${wt.dim(t)} ${wt.cyan(e.value)}`:`${o} ${n} ${t} ${e.value}`}function En(e){process.stdout.write(Pr(e)+`
77
+ `)}var Ht=[{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:[]}],Ba=Ht.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var Cr=["openai","anthropic","google"],Ir=["openai"];function Wt(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let o=t.length>0?t:[...Cr];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:[...Ir];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 Ze from"fs";import j from"path";var vn=[{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:""}],qa=vn.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function _n(e){return vn.find(t=>t.id===e)}function Ar(e){Ze.mkdirSync(e,{recursive:!0})}function z(e,t){Ar(j.dirname(e)),Ze.writeFileSync(e,t)}function he(e,t){let o=j.join(e,".env.example");Ze.existsSync(o)?Ze.appendFileSync(o,`
78
+ `+t):Ze.writeFileSync(o,t)}function wr(e){let t=`"use client";
79
79
  /**
80
80
  * PostHog browser SDK \u2014 lazy-initialized on first access.
81
81
  */
@@ -158,11 +158,11 @@ export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
158
158
 
159
159
  return <>{children}</>;
160
160
  }
161
- `;z(j.join(e,"src","lib","analytics","posthog.client.ts"),t),z(j.join(e,"src","lib","analytics","posthog.server.ts"),o),z(j.join(e,"src","components","analytics","AnalyticsProvider.tsx"),n)}function Pr(){return`# PostHog \u2014 product analytics
161
+ `;z(j.join(e,"src","lib","analytics","posthog.client.ts"),t),z(j.join(e,"src","lib","analytics","posthog.server.ts"),o),z(j.join(e,"src","components","analytics","AnalyticsProvider.tsx"),n)}function Rr(){return`# PostHog \u2014 product analytics
162
162
  POSTHOG_KEY=
163
163
  NEXT_PUBLIC_POSTHOG_KEY=
164
164
  NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
165
- `}function Cr(e){z(j.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
165
+ `}function kr(e){z(j.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
166
166
  /**
167
167
  * Plausible script tag \u2014 lightweight, privacy-friendly analytics.
168
168
  */
@@ -182,10 +182,10 @@ export function PlausibleScript() {
182
182
  />
183
183
  );
184
184
  }
185
- `)}function Ir(){return`# Plausible \u2014 privacy-friendly analytics
185
+ `)}function xr(){return`# Plausible \u2014 privacy-friendly analytics
186
186
  NEXT_PUBLIC_PLAUSIBLE_DOMAIN=
187
187
  NEXT_PUBLIC_PLAUSIBLE_SRC=https://plausible.io/js/script.js
188
- `}function Ar(e){z(j.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
188
+ `}function Tr(e){z(j.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
189
189
  /**
190
190
  * Umami analytics \u2014 self-hosted OR umami.is cloud.
191
191
  */
@@ -205,10 +205,10 @@ export function UmamiScript() {
205
205
  />
206
206
  );
207
207
  }
208
- `)}function wr(){return`# Umami \u2014 self-hostable analytics
208
+ `)}function Nr(){return`# Umami \u2014 self-hostable analytics
209
209
  NEXT_PUBLIC_UMAMI_WEBSITE_ID=
210
210
  NEXT_PUBLIC_UMAMI_SRC=https://cloud.umami.is/script.js
211
- `}function Rr(e){let t=`"use client";
211
+ `}function Or(e){let t=`"use client";
212
212
  import mixpanel from "mixpanel-browser";
213
213
 
214
214
  let initialized = false;
@@ -247,10 +247,10 @@ export function trackServer(
247
247
  if (!c) return;
248
248
  c.track(event, { distinct_id: distinctId, ...properties });
249
249
  }
250
- `;z(j.join(e,"src","lib","analytics","mixpanel.client.ts"),t),z(j.join(e,"src","lib","analytics","mixpanel.server.ts"),o)}function kr(){return`# Mixpanel \u2014 product analytics
250
+ `;z(j.join(e,"src","lib","analytics","mixpanel.client.ts"),t),z(j.join(e,"src","lib","analytics","mixpanel.server.ts"),o)}function Ur(){return`# Mixpanel \u2014 product analytics
251
251
  MIXPANEL_TOKEN=
252
252
  NEXT_PUBLIC_MIXPANEL_TOKEN=
253
- `}function xr(e){z(j.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
253
+ `}function Lr(e){z(j.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
254
254
  /**
255
255
  * \u767E\u5EA6\u7EDF\u8BA1 Baidu Tongji \u2014 hm.js \u57CB\u70B9\u811A\u672C.
256
256
  */
@@ -276,9 +276,9 @@ var _hmt = _hmt || [];
276
276
  />
277
277
  );
278
278
  }
279
- `)}function Nr(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
279
+ `)}function Mr(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
280
280
  NEXT_PUBLIC_BAIDU_STATS_ID=
281
- `}function Tr(e){z(j.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
281
+ `}function Dr(e){z(j.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
282
282
  /**
283
283
  * \u795E\u7B56\u5206\u6790 (Sensors Analytics) \u2014 sa-sdk-javascript \u5C01\u88C5.
284
284
  */
@@ -306,10 +306,10 @@ export function initSensors(): void {
306
306
  }
307
307
 
308
308
  export { sensors };
309
- `)}function Or(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
309
+ `)}function Fr(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
310
310
  NEXT_PUBLIC_SENSORS_SERVER_URL=
311
311
  NEXT_PUBLIC_SENSORS_APP_JS_URL=
312
- `}function Ur(e){z(j.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
312
+ `}function jr(e){z(j.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
313
313
  /**
314
314
  * GrowingIO CDP \u2014 inline snippet installer.
315
315
  */
@@ -334,21 +334,21 @@ gdp("send");
334
334
  />
335
335
  );
336
336
  }
337
- `)}function Lr(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
337
+ `)}function Vr(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
338
338
  NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID=
339
- `}async function vn(e,t,o="global"){let n=En(t);if(!n||n.id==="none")return;let r=j.join(e,"apps","web");if(!Qe.existsSync(r))return;let s=n.id;try{switch(s){case"posthog":br(r),he(e,Pr());return;case"plausible":Cr(r),he(e,Ir());return;case"umami":Ar(r),he(e,wr());return;case"mixpanel":Rr(r),he(e,kr());return;case"baidu":xr(r),he(e,Nr());return;case"sensors":Tr(r),he(e,Or());return;case"growingio":Ur(r),he(e,Lr());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 Mr="https://analytics.nebutra.com";function Dr(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function _n(e,t={}){Dr(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??Mr},onError:()=>{}});if(typeof n?.track!="function")return;let r=n.track("scaffold.completed",e);r&&typeof r.then=="function"&&await r.catch(()=>{})}catch{}})()}import B from"fs";import q from"path";function Ee(e){B.existsSync(e)&&B.rmSync(e,{recursive:!0,force:!0})}function Ht(e,t){let o=q.join(e,".env.example");B.existsSync(o)?B.appendFileSync(o,`
340
- `+t):B.writeFileSync(o,t)}function Wt(e,t){if(!B.existsSync(e))return;let o=B.readFileSync(e,"utf8"),n=o.replace(/export type AuthProviderId\s*=\s*(?:"[^"]+"\s*\|\s*)+"[^"]+";/,`export type AuthProviderId = "${t}";`);n!==o&&B.writeFileSync(e,n)}function Fr(e,t){let o=q.join(e,"README.md");if(!B.existsSync(o)){B.writeFileSync(o,t);return}B.appendFileSync(o,`
341
- `+t)}async function bn(e,t){let o=q.join(e,"packages","iam","auth");if(!B.existsSync(o))return;if(t==="none"){Ee(o),Fr(e,`
339
+ `}async function bn(e,t,o="global"){let n=_n(t);if(!n||n.id==="none")return;let r=j.join(e,"apps","web");if(!Ze.existsSync(r))return;let s=n.id;try{switch(s){case"posthog":wr(r),he(e,Rr());return;case"plausible":kr(r),he(e,xr());return;case"umami":Tr(r),he(e,Nr());return;case"mixpanel":Or(r),he(e,Ur());return;case"baidu":Lr(r),he(e,Mr());return;case"sensors":Dr(r),he(e,Fr());return;case"growingio":jr(r),he(e,Vr());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 Kr="https://analytics.nebutra.com";function Br(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function Pn(e,t={}){Br(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??Kr},onError:()=>{}});if(typeof n?.track!="function")return;let r=n.track("scaffold.completed",e);r&&typeof r.then=="function"&&await r.catch(()=>{})}catch{}})()}import B from"fs";import G from"path";function Ee(e){B.existsSync(e)&&B.rmSync(e,{recursive:!0,force:!0})}function Xt(e,t){let o=G.join(e,".env.example");B.existsSync(o)?B.appendFileSync(o,`
340
+ `+t):B.writeFileSync(o,t)}function zt(e,t){if(!B.existsSync(e))return;let o=B.readFileSync(e,"utf8"),n=o.replace(/export type AuthProviderId\s*=\s*(?:"[^"]+"\s*\|\s*)+"[^"]+";/,`export type AuthProviderId = "${t}";`);n!==o&&B.writeFileSync(e,n)}function $r(e,t){let o=G.join(e,"README.md");if(!B.existsSync(o)){B.writeFileSync(o,t);return}B.appendFileSync(o,`
341
+ `+t)}async function Cn(e,t){let o=G.join(e,"packages","iam","auth");if(!B.existsSync(o))return;if(t==="none"){Ee(o),$r(e,`
342
342
  ## Auth
343
343
 
344
344
  Auth was skipped at scaffold time (\`--auth=none\`). Add your preferred auth provider manually (e.g. Clerk, Better Auth).
345
- `);return}let n=q.join(o,"src","providers"),r=q.join(o,"src","types.ts");if(t==="clerk"){Ee(q.join(n,"better-auth.ts")),Ee(q.join(n,"nextauth.ts")),Wt(r,"clerk"),Ht(e,`# Clerk auth
345
+ `);return}let n=G.join(o,"src","providers"),r=G.join(o,"src","types.ts");if(t==="clerk"){Ee(G.join(n,"better-auth.ts")),Ee(G.join(n,"nextauth.ts")),zt(r,"clerk"),Xt(e,`# Clerk auth
346
346
  CLERK_PUBLISHABLE_KEY=
347
347
  CLERK_SECRET_KEY=
348
- `);return}if(t==="betterauth"){Ee(q.join(n,"clerk.ts")),Ee(q.join(n,"nextauth.ts")),Wt(r,"better-auth"),Ht(e,`# Better Auth
348
+ `);return}if(t==="betterauth"){Ee(G.join(n,"clerk.ts")),Ee(G.join(n,"nextauth.ts")),zt(r,"better-auth"),Xt(e,`# Better Auth
349
349
  BETTER_AUTH_SECRET=
350
350
  BETTER_AUTH_URL=http://localhost:3000
351
- `);return}if(t==="nextauth"){Ee(q.join(n,"clerk.ts")),Ee(q.join(n,"better-auth.ts")),Wt(r,"nextauth"),Ht(e,`# NextAuth (Auth.js v5)
351
+ `);return}if(t==="nextauth"){Ee(G.join(n,"clerk.ts")),Ee(G.join(n,"better-auth.ts")),zt(r,"nextauth"),Xt(e,`# NextAuth (Auth.js v5)
352
352
  AUTH_SECRET=
353
353
  NEXTAUTH_URL=http://localhost:3000
354
354
  # OAuth (optional \u2014 leave blank to disable that provider)
@@ -356,7 +356,7 @@ GOOGLE_CLIENT_ID=
356
356
  GOOGLE_CLIENT_SECRET=
357
357
  GITHUB_CLIENT_ID=
358
358
  GITHUB_CLIENT_SECRET=
359
- `);return}}var lt=[{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"}],jr=new Set(lt.map(e=>e.id));function Pn(e){return lt.find(t=>t.id===e)}function Cn(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)jr.has(r)&&!n.has(r)&&(o.push(r),n.add(r));return o}import _e from"fs";import ve from"path";function Vr(e,t){let o=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
359
+ `);return}}var dt=[{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"}],Yr=new Set(dt.map(e=>e.id));function In(e){return dt.find(t=>t.id===e)}function An(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)Yr.has(r)&&!n.has(r)&&(o.push(r),n.add(r));return o}import _e from"fs";import ve from"path";function qr(e,t){let o=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
360
360
  // Generated by create-sailor \u2014 OAuth callback for ${e.name}
361
361
  // Primary auth provider: ${t}
362
362
  // Docs: ${e.docs}`,n={wechat:` const tokenRes = await fetch(
@@ -481,7 +481,7 @@ ${n[e.id]}
481
481
  void state;
482
482
  return NextResponse.redirect(new URL("/dashboard", req.url));
483
483
  }
484
- `}function Kr(e){return`"use client";
484
+ `}function Gr(e){return`"use client";
485
485
 
486
486
  /**
487
487
  * SocialLoginButtons \u2014 generated by create-sailor.
@@ -524,23 +524,23 @@ export function SocialLoginButtons() {
524
524
  </div>
525
525
  );
526
526
  }
527
- `}function In(e){_e.mkdirSync(e,{recursive:!0})}function Br(e,t){let o=ve.join(e,".env.example");_e.existsSync(o)?_e.appendFileSync(o,`
528
- `+t):_e.writeFileSync(o,t)}function $r(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,o=e.envVars.map(n=>`${n}=`).join(`
527
+ `}function wn(e){_e.mkdirSync(e,{recursive:!0})}function Hr(e,t){let o=ve.join(e,".env.example");_e.existsSync(o)?_e.appendFileSync(o,`
528
+ `+t):_e.writeFileSync(o,t)}function Wr(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,o=e.envVars.map(n=>`${n}=`).join(`
529
529
  `);return`${t}
530
530
  ${o}
531
- `}async function An(e,t,o){if(!t||t.length===0)return;let n=ve.join(e,"apps","web");if(!_e.existsSync(n))return;let r=new Set,s=[];for(let l of t){if(r.has(l))continue;r.add(l);let m=Pn(l);m&&s.push(m)}if(s.length===0)return;for(let l of s)Br(e,$r(l));let i=ve.join(n,"src","app","api","auth","callback");for(let l of s){let m=ve.join(i,l.id);In(m);let S=ve.join(m,"route.ts");_e.writeFileSync(S,Vr(l,o))}let c=ve.join(n,"src","components","auth");In(c);let a=ve.join(c,"SocialLoginButtons.tsx");_e.writeFileSync(a,Kr(s))}import Ze from"fs";import Rn from"path";var wt=[{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 wn(e){return wt.find(t=>t.id===e)}var Qa=wt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import J from"fs";import Rt from"path";function Q(e,t){let o=Rt.join(e,".env.example");if(!J.existsSync(o)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(J.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(`
532
- `);J.appendFileSync(o,c)}function Z(e,t,o){let n=Rt.join(e,".env.example");if(!J.existsSync(n))return;let r=J.readFileSync(n,"utf-8"),s=`${t}="${o}"`,i=new RegExp(`^${t}=.*$`,"m");if(i.test(r)){J.writeFileSync(n,r.replace(i,s));return}let c=r.endsWith(`
531
+ `}async function Rn(e,t,o){if(!t||t.length===0)return;let n=ve.join(e,"apps","web");if(!_e.existsSync(n))return;let r=new Set,s=[];for(let l of t){if(r.has(l))continue;r.add(l);let m=In(l);m&&s.push(m)}if(s.length===0)return;for(let l of s)Hr(e,Wr(l));let i=ve.join(n,"src","app","api","auth","callback");for(let l of s){let m=ve.join(i,l.id);wn(m);let S=ve.join(m,"route.ts");_e.writeFileSync(S,qr(l,o))}let c=ve.join(n,"src","components","auth");wn(c);let a=ve.join(c,"SocialLoginButtons.tsx");_e.writeFileSync(a,Gr(s))}import et from"fs";import xn from"path";var Rt=[{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 kn(e){return Rt.find(t=>t.id===e)}var ic=Rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import J from"fs";import kt from"path";function Q(e,t){let o=kt.join(e,".env.example");if(!J.existsSync(o)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(J.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(`
532
+ `);J.appendFileSync(o,c)}function Z(e,t,o){let n=kt.join(e,".env.example");if(!J.existsSync(n))return;let r=J.readFileSync(n,"utf-8"),s=`${t}="${o}"`,i=new RegExp(`^${t}=.*$`,"m");if(i.test(r)){J.writeFileSync(n,r.replace(i,s));return}let c=r.endsWith(`
533
533
  `)?"":`
534
534
  `;J.appendFileSync(n,`${c}${s}
535
- `)}var Yr=["design","iam","commerce","integrations","platform","ops","ai"];function be(e,t){for(let n of Yr){let r=Rt.join(e,"packages",n,t);if(J.existsSync(r))return r}let o=Rt.join(e,"packages",t);return J.existsSync(o)?o:null}function G(e,t){let o=be(e,t);o&&J.rmSync(o,{recursive:!0,force:!0})}function kn(e){return Ze.existsSync(e)?Ze.readFileSync(e,"utf-8"):null}function qr(e,t){let o=Rn.join(e,".env.example"),n=kn(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(`
536
- `);Ze.appendFileSync(o,s)}function Gr(e,t,o){let n=Rn.join(e,".env.example"),r=kn(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?Ze.writeFileSync(n,r.replace(s,`${t}="${o}"`)):Ze.appendFileSync(n,`${t}="${o}"
537
- `)}async function xn(e,t,o){let n=be(e,"cache");if(t==="none"){n&&Ze.rmSync(n,{recursive:!0,force:!0});return}let r=wn(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${wt.map(s=>s.id).join(", ")}`);n&&(qr(e,r),Gr(e,"CACHE_PROVIDER",t))}var kt=[{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 Nn(e){return kt.find(t=>t.id===e)}var cc=kt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Tn(e,t,o="global"){let n=Nn(t);if(!n)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${kt.map(r=>r.id).join(", ")}`);if(n.id==="none"){G(e,"captcha");return}n.envVars.length>0&&Q(e,{category:"Captcha",name:n.name,envVars:n.envVars,docs:n.docs}),Z(e,"CAPTCHA_PROVIDER",n.id)}import Nt from"fs";import Hr from"path";var xt=[{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 On(e){return xt.find(t=>t.id===e)}var mc=xt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Un(e,t,o="global"){let n=On(t);if(!n)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${xt.map(s=>s.id).join(", ")}`);let r=Hr.join(e,"apps","studio");if(n.id==="none"){G(e,"sanity"),Nt.existsSync(r)&&Nt.rmSync(r,{recursive:!0,force:!0});return}n.id!=="sanity"&&(G(e,"sanity"),Nt.existsSync(r)&&Nt.rmSync(r,{recursive:!0,force:!0})),n.envVars.length>0&&Q(e,{category:"CMS",name:n.name,envVars:n.envVars,docs:n.docs}),Z(e,"CMS_PROVIDER",n.id)}import k from"fs";import R from"path";var Wr=R.join("apps","web"),Xt=R.join("src","components","compliance"),dt=R.join("src","app","[locale]");function ee(e){return R.join(e,Wr)}function Xr(e){k.mkdirSync(e,{recursive:!0})}function H(e,t){Xr(R.dirname(e)),k.writeFileSync(e,t,"utf8")}function zt(e,t){let o=R.join(e,".env.example");if(k.existsSync(o)){if(k.readFileSync(o,"utf8").includes(t.split(`
535
+ `)}var Xr=["design","iam","commerce","integrations","platform","ops","ai"];function be(e,t){for(let n of Xr){let r=kt.join(e,"packages",n,t);if(J.existsSync(r))return r}let o=kt.join(e,"packages",t);return J.existsSync(o)?o:null}function H(e,t){let o=be(e,t);o&&J.rmSync(o,{recursive:!0,force:!0})}function Tn(e){return et.existsSync(e)?et.readFileSync(e,"utf-8"):null}function zr(e,t){let o=xn.join(e,".env.example"),n=Tn(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(`
536
+ `);et.appendFileSync(o,s)}function Jr(e,t,o){let n=xn.join(e,".env.example"),r=Tn(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?et.writeFileSync(n,r.replace(s,`${t}="${o}"`)):et.appendFileSync(n,`${t}="${o}"
537
+ `)}async function Nn(e,t,o){let n=be(e,"cache");if(t==="none"){n&&et.rmSync(n,{recursive:!0,force:!0});return}let r=kn(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${Rt.map(s=>s.id).join(", ")}`);n&&(zr(e,r),Jr(e,"CACHE_PROVIDER",t))}var xt=[{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 On(e){return xt.find(t=>t.id===e)}var yc=xt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Un(e,t,o="global"){let n=On(t);if(!n)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${xt.map(r=>r.id).join(", ")}`);if(n.id==="none"){H(e,"captcha");return}n.envVars.length>0&&Q(e,{category:"Captcha",name:n.name,envVars:n.envVars,docs:n.docs}),Z(e,"CAPTCHA_PROVIDER",n.id)}import Nt from"fs";import Qr from"path";var Tt=[{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 Ln(e){return Tt.find(t=>t.id===e)}var _c=Tt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Mn(e,t,o="global"){let n=Ln(t);if(!n)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${Tt.map(s=>s.id).join(", ")}`);let r=Qr.join(e,"apps","studio");if(n.id==="none"){H(e,"sanity"),Nt.existsSync(r)&&Nt.rmSync(r,{recursive:!0,force:!0});return}n.id!=="sanity"&&(H(e,"sanity"),Nt.existsSync(r)&&Nt.rmSync(r,{recursive:!0,force:!0})),n.envVars.length>0&&Q(e,{category:"CMS",name:n.name,envVars:n.envVars,docs:n.docs}),Z(e,"CMS_PROVIDER",n.id)}import k from"fs";import R from"path";var Zr=R.join("apps","web"),Jt=R.join("src","components","compliance"),ut=R.join("src","app","[locale]");function ee(e){return R.join(e,Zr)}function es(e){k.mkdirSync(e,{recursive:!0})}function W(e,t){es(R.dirname(e)),k.writeFileSync(e,t,"utf8")}function Qt(e,t){let o=R.join(e,".env.example");if(k.existsSync(o)){if(k.readFileSync(o,"utf8").includes(t.split(`
538
538
  `)[0]??""))return;k.appendFileSync(o,`
539
539
  `+t+`
540
540
  `)}else k.writeFileSync(o,t+`
541
- `)}var ut=`> **TEMPLATE \u2014 NOT LEGAL ADVICE.** This document is a boilerplate scaffold only.
541
+ `)}var mt=`> **TEMPLATE \u2014 NOT LEGAL ADVICE.** This document is a boilerplate scaffold only.
542
542
  > Consult a qualified lawyer in every jurisdiction you operate in before publishing.
543
- > \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`,zr=`import Link from "next/link";
543
+ > \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`,ts=`import Link from "next/link";
544
544
  import { IcpFooter } from "@/components/compliance/IcpFooter";
545
545
  import { PublicSecurityFooter } from "@/components/compliance/PublicSecurityFooter";
546
546
 
@@ -591,7 +591,7 @@ export function Footer({ region = "global" }: FooterProps) {
591
591
  </footer>
592
592
  );
593
593
  }
594
- `,Jr=`export function IcpFooter() {
594
+ `,ns=`export function IcpFooter() {
595
595
  const icp = process.env.NEXT_PUBLIC_ICP_BEIAN;
596
596
  if (!icp) return null;
597
597
  return (
@@ -605,7 +605,7 @@ export function Footer({ region = "global" }: FooterProps) {
605
605
  </a>
606
606
  );
607
607
  }
608
- `,Qr=`export function PublicSecurityFooter() {
608
+ `,os=`export function PublicSecurityFooter() {
609
609
  const psb = process.env.NEXT_PUBLIC_PSB_BEIAN;
610
610
  const psbCode = process.env.NEXT_PUBLIC_PSB_CODE;
611
611
  if (!psb) return null;
@@ -622,7 +622,7 @@ export function Footer({ region = "global" }: FooterProps) {
622
622
  </a>
623
623
  );
624
624
  }
625
- `,Zr=`"use client";
625
+ `,rs=`"use client";
626
626
 
627
627
  import { useCallback, useEffect, useState } from "react";
628
628
 
@@ -849,7 +849,7 @@ function CategoryRow({ id, title, description, checked, disabled, onChange }: Ca
849
849
  </label>
850
850
  );
851
851
  }
852
- `,es=`interface AigcDisclaimerProps {
852
+ `,ss=`interface AigcDisclaimerProps {
853
853
  className?: string;
854
854
  }
855
855
 
@@ -869,13 +869,13 @@ export function AigcDisclaimer({ className }: AigcDisclaimerProps) {
869
869
  </div>
870
870
  );
871
871
  }
872
- `,ts=`---
872
+ `,is=`---
873
873
  title: Privacy Policy / \u9690\u79C1\u653F\u7B56
874
874
  description: How {{COMPANY_NAME}} collects, uses, shares, and protects personal information.
875
875
  lastUpdated: 2026-01-01
876
876
  ---
877
877
 
878
- ${ut}
878
+ ${mt}
879
879
 
880
880
  # Privacy Policy / \u9690\u79C1\u653F\u7B56
881
881
 
@@ -1014,13 +1014,13 @@ or in-app notification before the change takes effect.
1014
1014
  **Data Controller / \u6570\u636E\u63A7\u5236\u8005:** {{COMPANY_NAME}}
1015
1015
  **Address / \u5730\u5740:** {{COMPANY_ADDRESS}}
1016
1016
  **Email / \u90AE\u7BB1:** {{COMPANY_CONTACT_EMAIL}}
1017
- `,ns=`---
1017
+ `,as=`---
1018
1018
  title: Terms of Service / \u670D\u52A1\u6761\u6B3E
1019
1019
  description: Terms governing your use of {{COMPANY_NAME}}.
1020
1020
  lastUpdated: 2026-01-01
1021
1021
  ---
1022
1022
 
1023
- ${ut}
1023
+ ${mt}
1024
1024
 
1025
1025
  # Terms of Service / \u670D\u52A1\u6761\u6B3E
1026
1026
 
@@ -1133,13 +1133,13 @@ conflict-of-laws principles. Disputes shall be resolved in the competent courts
1133
1133
  ## 11. Contact / \u8054\u7CFB\u65B9\u5F0F
1134
1134
 
1135
1135
  {{COMPANY_NAME}} \xB7 {{COMPANY_ADDRESS}} \xB7 {{COMPANY_CONTACT_EMAIL}}
1136
- `,os=`---
1136
+ `,cs=`---
1137
1137
  title: AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
1138
1138
  description: Disclosure required by \u7F51\u4FE1\u529E\u300A\u751F\u6210\u5F0F\u4EBA\u5DE5\u667A\u80FD\u670D\u52A1\u7BA1\u7406\u6682\u884C\u529E\u6CD5\u300B
1139
1139
  lastUpdated: 2026-01-01
1140
1140
  ---
1141
1141
 
1142
- ${ut}
1142
+ ${mt}
1143
1143
 
1144
1144
  # AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
1145
1145
 
@@ -1215,13 +1215,13 @@ human professional.
1215
1215
 
1216
1216
  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
1217
1217
  \u7528\u4E8E\u533B\u7597\u3001\u6CD5\u5F8B\u3001\u91D1\u878D\u6216\u5B89\u5168\u6538\u5173\u7684\u51B3\u7B56\u3002
1218
- `,rs=`---
1218
+ `,ps=`---
1219
1219
  title: Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
1220
1220
  description: Notice of cross-border transfer of personal information, per PIPL.
1221
1221
  lastUpdated: 2026-01-01
1222
1222
  ---
1223
1223
 
1224
- ${ut}
1224
+ ${mt}
1225
1225
 
1226
1226
  # Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
1227
1227
 
@@ -1280,13 +1280,13 @@ Refusal may limit your ability to use features that rely on overseas services.
1280
1280
  - \u4F20\u8F93\u4E2D\u52A0\u5BC6 (TLS 1.2+) \u53CA\u9759\u6001\u52A0\u5BC6 (AES-256)\u3002
1281
1281
  - \u5408\u540C\u6761\u6B3E\u8981\u6C42\u5883\u5916\u63A5\u6536\u65B9\u63D0\u4F9B\u7B49\u540C\u4E8E PIPL \u7684\u4FDD\u62A4\u3002
1282
1282
  - \u8BBF\u95EE\u63A7\u5236\u3001\u5BA1\u8BA1\u65E5\u5FD7\u548C\u8FDD\u89C4\u901A\u77E5\u7A0B\u5E8F\u3002
1283
- `,ss=`---
1283
+ `,ls=`---
1284
1284
  title: Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
1285
1285
  description: Itemized list of personal information collected, per PIPL Article 17.
1286
1286
  lastUpdated: 2026-01-01
1287
1287
  ---
1288
1288
 
1289
- ${ut}
1289
+ ${mt}
1290
1290
 
1291
1291
  # Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
1292
1292
 
@@ -1322,26 +1322,26 @@ To exercise your rights (access, rectify, delete, export, withdraw consent), con
1322
1322
  **{{COMPANY_CONTACT_EMAIL}}**.
1323
1323
 
1324
1324
  \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
1325
- `;async function is(e,t){let o=ee(e);if(!k.existsSync(o))return;let n=R.join(o,"src","components","compliance","Footer.tsx");H(n,zr);let r=R.join(o,"src","components","compliance","README.md");H(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(`
1326
- `))}async function as(e,t){let o=ee(e);if(!k.existsSync(o))return;let n=R.join(o,"src","components","compliance","CookieBanner.tsx");H(n,Zr)}async function cs(e,t){let o=ee(e);if(!k.existsSync(o))return;let n=R.join(o,dt,"privacy","page.mdx");H(n,ts)}async function ps(e,t){let o=ee(e);if(!k.existsSync(o))return;let n=R.join(o,dt,"terms","page.mdx");H(n,ns)}async function ls(e){let t=ee(e);if(!k.existsSync(t))return;let o=R.join(t,Xt,"IcpFooter.tsx");H(o,Jr),zt(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(`
1327
- `))}async function ds(e){let t=ee(e);if(!k.existsSync(t))return;let o=R.join(t,Xt,"PublicSecurityFooter.tsx");H(o,Qr),zt(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(`
1328
- `))}async function us(e){let t=ee(e);if(!k.existsSync(t))return;let o=R.join(t,Xt,"AigcDisclaimer.tsx");H(o,es),zt(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(`
1329
- `))}async function ms(e){let t=ee(e);if(!k.existsSync(t))return;let o=R.join(t,dt,"aigc-disclosure","page.mdx");H(o,os)}async function gs(e){let t=ee(e);if(!k.existsSync(t))return;let o=R.join(t,dt,"cross-border-data","page.mdx");H(o,rs)}async function fs(e){let t=ee(e);if(!k.existsSync(t))return;let o=R.join(t,dt,"pii-collection","page.mdx");H(o,ss)}async function Ln(e,t){try{await is(e,t),await as(e,t),await cs(e,t),await ps(e,t),(t==="cn"||t==="hybrid")&&(await ls(e),await ds(e),await us(e),await ms(e),await gs(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 ys from"fs";import Ss from"path";async function Mn(e,t){let o=Ss.join(e,"nebutra.config.json");ys.writeFileSync(o,JSON.stringify(t,null,2)+`
1330
- `)}import A from"fs";import Pe from"path";var Jt=[{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 Tt(e){return Jt.find(t=>t.id===e)}function Dn(e){return e==="cn"||e==="hybrid"?"local":"supabase"}function hs(e){A.existsSync(e)&&A.rmSync(e,{recursive:!0,force:!0})}function Fn(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function Es(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function jn(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 vs(e,t){let o=Pe.join(e,".env.example");A.existsSync(o)?A.appendFileSync(o,`
1331
- `+t):A.writeFileSync(o,t)}async function Vn(e,t,o){let n=Pe.join(e,"packages","platform","db");if(t==="none"){hs(n);return}let r=Pe.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",vs(e,`# Database (${t})
1325
+ `;async function ds(e,t){let o=ee(e);if(!k.existsSync(o))return;let n=R.join(o,"src","components","compliance","Footer.tsx");W(n,ts);let r=R.join(o,"src","components","compliance","README.md");W(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(`
1326
+ `))}async function us(e,t){let o=ee(e);if(!k.existsSync(o))return;let n=R.join(o,"src","components","compliance","CookieBanner.tsx");W(n,rs)}async function ms(e,t){let o=ee(e);if(!k.existsSync(o))return;let n=R.join(o,ut,"privacy","page.mdx");W(n,is)}async function gs(e,t){let o=ee(e);if(!k.existsSync(o))return;let n=R.join(o,ut,"terms","page.mdx");W(n,as)}async function fs(e){let t=ee(e);if(!k.existsSync(t))return;let o=R.join(t,Jt,"IcpFooter.tsx");W(o,ns),Qt(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(`
1327
+ `))}async function ys(e){let t=ee(e);if(!k.existsSync(t))return;let o=R.join(t,Jt,"PublicSecurityFooter.tsx");W(o,os),Qt(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(`
1328
+ `))}async function Ss(e){let t=ee(e);if(!k.existsSync(t))return;let o=R.join(t,Jt,"AigcDisclaimer.tsx");W(o,ss),Qt(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(`
1329
+ `))}async function hs(e){let t=ee(e);if(!k.existsSync(t))return;let o=R.join(t,ut,"aigc-disclosure","page.mdx");W(o,cs)}async function Es(e){let t=ee(e);if(!k.existsSync(t))return;let o=R.join(t,ut,"cross-border-data","page.mdx");W(o,ps)}async function vs(e){let t=ee(e);if(!k.existsSync(t))return;let o=R.join(t,ut,"pii-collection","page.mdx");W(o,ls)}async function Dn(e,t){try{await ds(e,t),await us(e,t),await ms(e,t),await gs(e,t),(t==="cn"||t==="hybrid")&&(await fs(e),await ys(e),await Ss(e),await hs(e),await Es(e),await vs(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 _s from"fs";import bs from"path";async function Fn(e,t){let o=bs.join(e,"nebutra.config.json");_s.writeFileSync(o,JSON.stringify(t,null,2)+`
1330
+ `)}import A from"fs";import Pe from"path";var Zt=[{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 Ot(e){return Zt.find(t=>t.id===e)}function jn(e){return e==="cn"||e==="hybrid"?"local":"supabase"}function Ps(e){A.existsSync(e)&&A.rmSync(e,{recursive:!0,force:!0})}function Vn(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function Cs(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function Kn(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 Is(e,t){let o=Pe.join(e,".env.example");A.existsSync(o)?A.appendFileSync(o,`
1331
+ `+t):A.writeFileSync(o,t)}async function Bn(e,t,o){let n=Pe.join(e,"packages","platform","db");if(t==="none"){Ps(n);return}let r=Pe.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",Is(e,`# Database (${t})
1332
1332
  DATABASE_URL="${s}"
1333
- `),!A.existsSync(r))return;let i=A.readFileSync(r,"utf8"),c=i;t==="mysql"?(c=Fn(c,"mysql"),c=jn(c)):t==="sqlite"&&(c=Fn(c,"sqlite"),c=Es(c),c=jn(c)),c!==i&&A.writeFileSync(r,c)}function _s(e){let t=Pe.join(e,".env.example");return A.existsSync(t)?A.readFileSync(t,"utf8"):""}function bs(e,t,o,n){let r=Pe.join(e,".env.example"),s=_s(e),i=n?`# ${n}
1333
+ `),!A.existsSync(r))return;let i=A.readFileSync(r,"utf8"),c=i;t==="mysql"?(c=Vn(c,"mysql"),c=Kn(c)):t==="sqlite"&&(c=Vn(c,"sqlite"),c=Cs(c),c=Kn(c)),c!==i&&A.writeFileSync(r,c)}function As(e){let t=Pe.join(e,".env.example");return A.existsSync(t)?A.readFileSync(t,"utf8"):""}function ws(e,t,o,n){let r=Pe.join(e,".env.example"),s=As(e),i=n?`# ${n}
1334
1334
  ${t}="${o}"
1335
1335
  `:`${t}="${o}"
1336
1336
  `,c=new RegExp(`^\\s*${t}\\s*=.*$`,"m");if(c.test(s)){A.writeFileSync(r,s.replace(c,`${t}="${o}"`));return}s?A.appendFileSync(r,`
1337
- ${i}`):A.writeFileSync(r,i)}function Ps(e,t){let o=Pe.join(e,"packages","platform","db","prisma","schema.prisma");if(!A.existsSync(o))return;let n=A.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(`
1337
+ ${i}`):A.writeFileSync(r,i)}function Rs(e,t){let o=Pe.join(e,"packages","platform","db","prisma","schema.prisma");if(!A.existsSync(o))return;let n=A.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(`
1338
1338
  `),a=n.replace(r,`$1
1339
- ${c}$2`);A.writeFileSync(o,a)}function Cs(e){let t=Pe.join(e,"packages","platform","db","prisma","schema.prisma");if(!A.existsSync(t))return;let o=A.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)&&A.writeFileSync(t,o.replace(n,`$1 directUrl = env("DIRECT_URL")
1340
- `))}async function Kn(e,t,o){if(!(t.id==="none"||t.id==="local")){for(let n of t.envVars){let r=n.placeholder.replace(/\$PROJECT/g,o);bs(e,n.name,r,n.comment)}t.prismaDatasourceExtras&&t.prismaDatasourceExtras.length>0&&Ps(e,t.prismaDatasourceExtras),t.keepDirectUrl&&Cs(e)}}import et from"fs";import V from"path";import{fileURLToPath as Is}from"url";var As=Is(import.meta.url),Bn=V.dirname(As);function ws(){let e=[V.join(Bn,"..","templates","deploy"),V.join(Bn,"..","..","templates","deploy")];for(let t of e)if(et.existsSync(t))return t;return e[0]}async function $n(e,t){if(t==="none")return;let o=ws();t==="vercel"?await et.promises.copyFile(V.join(o,"vercel.json"),V.join(e,"vercel.json")):t==="railway"?await et.promises.copyFile(V.join(o,"railway.toml"),V.join(e,"railway.toml")):t==="cloudflare"?await et.promises.copyFile(V.join(o,"wrangler.toml"),V.join(e,"wrangler.toml")):t==="selfhost"&&(await et.promises.copyFile(V.join(o,"docker-compose.yml"),V.join(e,"docker-compose.yml")),await et.promises.copyFile(V.join(o,"Dockerfile.web"),V.join(e,"Dockerfile.web")))}import pe from"fs";import Ce from"path";import{fileURLToPath as Rs}from"url";var ks=Rs(import.meta.url),Yn=Ce.dirname(ks),xs=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,qn=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function Ns(e){let t=[Ce.join(Yn,"..","templates","docs",e),Ce.join(Yn,"..","..","templates","docs",e)];for(let o of t)if(pe.existsSync(o))return o;return t[0]}async function Gn(e,t){if(t.framework==="none")return;if(!qn.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${qn.join(", ")}, none.`);let o=Ns(t.framework),n=Ce.join(e,"apps","docs");if(!pe.existsSync(o))throw new Error(`Docs template not found: ${o}`);Hn(o,n),Wn(n,{"{PRODUCT_NAME}":t.projectName})}function Hn(e,t){pe.mkdirSync(t,{recursive:!0});for(let o of pe.readdirSync(e,{withFileTypes:!0})){let n=Ce.join(e,o.name),r=Ce.join(t,o.name);o.isDirectory()?Hn(n,r):pe.copyFileSync(n,r)}}function Wn(e,t){for(let o of pe.readdirSync(e,{withFileTypes:!0})){let n=Ce.join(e,o.name);if(o.isDirectory())Wn(n,t);else if(xs.test(o.name)){let r=pe.readFileSync(n,"utf-8");for(let[s,i]of Object.entries(t))r=r.split(s).join(i);pe.writeFileSync(n,r)}}}import Ae from"fs";import Ie from"path";var Ot=[{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 Xn(e){return Ot.find(t=>t.id===e)}var jc=Ot.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var we="@nebutra/email";function Qt(e,t){Ae.mkdirSync(Ie.dirname(e),{recursive:!0}),Ae.writeFileSync(e,t)}function Ts(e,t){let o=Ie.join(e,".env.example");Ae.existsSync(o)?Ae.appendFileSync(o,`
1341
- `+t):Ae.writeFileSync(o,t)}function Os(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
1339
+ ${c}$2`);A.writeFileSync(o,a)}function ks(e){let t=Pe.join(e,"packages","platform","db","prisma","schema.prisma");if(!A.existsSync(t))return;let o=A.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)&&A.writeFileSync(t,o.replace(n,`$1 directUrl = env("DIRECT_URL")
1340
+ `))}async function $n(e,t,o){if(!(t.id==="none"||t.id==="local")){for(let n of t.envVars){let r=n.placeholder.replace(/\$PROJECT/g,o);ws(e,n.name,r,n.comment)}t.prismaDatasourceExtras&&t.prismaDatasourceExtras.length>0&&Rs(e,t.prismaDatasourceExtras),t.keepDirectUrl&&ks(e)}}import tt from"fs";import V from"path";import{fileURLToPath as xs}from"url";var Ts=xs(import.meta.url),Yn=V.dirname(Ts);function Ns(){let e=[V.join(Yn,"..","templates","deploy"),V.join(Yn,"..","..","templates","deploy")];for(let t of e)if(tt.existsSync(t))return t;return e[0]}async function qn(e,t){if(t==="none")return;let o=Ns();t==="vercel"?await tt.promises.copyFile(V.join(o,"vercel.json"),V.join(e,"vercel.json")):t==="railway"?await tt.promises.copyFile(V.join(o,"railway.toml"),V.join(e,"railway.toml")):t==="cloudflare"?await tt.promises.copyFile(V.join(o,"wrangler.toml"),V.join(e,"wrangler.toml")):t==="selfhost"&&(await tt.promises.copyFile(V.join(o,"docker-compose.yml"),V.join(e,"docker-compose.yml")),await tt.promises.copyFile(V.join(o,"Dockerfile.web"),V.join(e,"Dockerfile.web")))}import pe from"fs";import Ce from"path";import{fileURLToPath as Os}from"url";var Us=Os(import.meta.url),Gn=Ce.dirname(Us),Ls=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,Hn=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function Ms(e){let t=[Ce.join(Gn,"..","templates","docs",e),Ce.join(Gn,"..","..","templates","docs",e)];for(let o of t)if(pe.existsSync(o))return o;return t[0]}async function Wn(e,t){if(t.framework==="none")return;if(!Hn.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${Hn.join(", ")}, none.`);let o=Ms(t.framework),n=Ce.join(e,"apps","docs");if(!pe.existsSync(o))throw new Error(`Docs template not found: ${o}`);Xn(o,n),zn(n,{"{PRODUCT_NAME}":t.projectName})}function Xn(e,t){pe.mkdirSync(t,{recursive:!0});for(let o of pe.readdirSync(e,{withFileTypes:!0})){let n=Ce.join(e,o.name),r=Ce.join(t,o.name);o.isDirectory()?Xn(n,r):pe.copyFileSync(n,r)}}function zn(e,t){for(let o of pe.readdirSync(e,{withFileTypes:!0})){let n=Ce.join(e,o.name);if(o.isDirectory())zn(n,t);else if(Ls.test(o.name)){let r=pe.readFileSync(n,"utf-8");for(let[s,i]of Object.entries(t))r=r.split(s).join(i);pe.writeFileSync(n,r)}}}import Ae from"fs";import Ie from"path";var Ut=[{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 Jn(e){return Ut.find(t=>t.id===e)}var Hc=Ut.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var we="@nebutra/email";function en(e,t){Ae.mkdirSync(Ie.dirname(e),{recursive:!0}),Ae.writeFileSync(e,t)}function Ds(e,t){let o=Ie.join(e,".env.example");Ae.existsSync(o)?Ae.appendFileSync(o,`
1341
+ `+t):Ae.writeFileSync(o,t)}function Fs(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
1342
1342
  `);return`${t}
1343
1343
  ${o}
1344
- `}var Us=`/**
1344
+ `}var js=`/**
1345
1345
  * Public inputs accepted by the \`sendEmail\` wrapper.
1346
1346
  * Keep the surface minimal \u2014 individual providers may accept more, but
1347
1347
  * consumers should code against this shape for portability.
@@ -1361,7 +1361,7 @@ export interface SendEmailResult {
1361
1361
  /** Raw provider response \u2014 useful for debugging, not a stable contract. */
1362
1362
  raw?: unknown;
1363
1363
  }
1364
- `;function Ls(){return`/**
1364
+ `;function Vs(){return`/**
1365
1365
  * @${we.slice(1)} \u2014 Resend transactional email wrapper.
1366
1366
  *
1367
1367
  * Docs: https://resend.com/docs
@@ -1400,7 +1400,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1400
1400
  }
1401
1401
 
1402
1402
  export type { SendEmailInput, SendEmailResult } from "./types";
1403
- `}function Ms(){return`/**
1403
+ `}function Ks(){return`/**
1404
1404
  * @${we.slice(1)} \u2014 Postmark transactional email wrapper.
1405
1405
  *
1406
1406
  * Docs: https://postmarkapp.com/developer
@@ -1438,7 +1438,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1438
1438
  }
1439
1439
 
1440
1440
  export type { SendEmailInput, SendEmailResult } from "./types";
1441
- `}function Ds(){return`/**
1441
+ `}function Bs(){return`/**
1442
1442
  * @${we.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1443
1443
  *
1444
1444
  * Docs: https://docs.aws.amazon.com/ses
@@ -1494,7 +1494,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1494
1494
  }
1495
1495
 
1496
1496
  export type { SendEmailInput, SendEmailResult } from "./types";
1497
- `}function Fs(){return`/**
1497
+ `}function $s(){return`/**
1498
1498
  * @${we.slice(1)} \u2014 \u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001 (Aliyun DirectMail) wrapper.
1499
1499
  *
1500
1500
  * Docs: https://help.aliyun.com/product/29412.html
@@ -1544,7 +1544,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1544
1544
  }
1545
1545
 
1546
1546
  export type { SendEmailInput, SendEmailResult } from "./types";
1547
- `}function js(){return`/**
1547
+ `}function Ys(){return`/**
1548
1548
  * @${we.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1549
1549
  *
1550
1550
  * Docs: https://cloud.tencent.com/document/product/1288
@@ -1592,7 +1592,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1592
1592
  }
1593
1593
 
1594
1594
  export type { SendEmailInput, SendEmailResult } from "./types";
1595
- `}function Vs(){return`/**
1595
+ `}function qs(){return`/**
1596
1596
  * @${we.slice(1)} \u2014 \u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1 via SMTP (nodemailer).
1597
1597
  *
1598
1598
  * Docs: https://qiye.163.com/help
@@ -1630,24 +1630,24 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1630
1630
  }
1631
1631
 
1632
1632
  export type { SendEmailInput, SendEmailResult } from "./types";
1633
- `}function Ks(e){switch(e){case"resend":return Ls();case"postmark":return Ms();case"ses":return Ds();case"aliyun-dm":return Fs();case"tencent-ses":return js();case"netease":return Vs();case"none":return`export {};
1634
- `}}function Bs(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:we,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)+`
1635
- `}async function zn(e,t,o){if(t==="none")return;let n=Xn(t);if(!n)throw new Error(`Unknown email provider "${t}". Valid ids: ${Ot.map(i=>i.id).join(", ")}`);let r=Ie.join(e,"packages","email"),s=Ie.join(r,"src");Ae.existsSync(s)&&Ae.rmSync(s,{recursive:!0,force:!0}),Qt(Ie.join(r,"package.json"),Bs(n)),Qt(Ie.join(s,"types.ts"),Us),Qt(Ie.join(s,"index.ts"),Ks(n.id)),Ts(e,Os(n))}import Ut from"fs";import Jn from"path";async function Qn(e,t){let o=`# Automatically injected by create-sailor
1633
+ `}function Gs(e){switch(e){case"resend":return Vs();case"postmark":return Ks();case"ses":return Bs();case"aliyun-dm":return $s();case"tencent-ses":return Ys();case"netease":return qs();case"none":return`export {};
1634
+ `}}function Hs(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:we,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)+`
1635
+ `}async function Qn(e,t,o){if(t==="none")return;let n=Jn(t);if(!n)throw new Error(`Unknown email provider "${t}". Valid ids: ${Ut.map(i=>i.id).join(", ")}`);let r=Ie.join(e,"packages","email"),s=Ie.join(r,"src");Ae.existsSync(s)&&Ae.rmSync(s,{recursive:!0,force:!0}),en(Ie.join(r,"package.json"),Hs(n)),en(Ie.join(s,"types.ts"),js),en(Ie.join(s,"index.ts"),Gs(n.id)),Ds(e,Fs(n))}import Lt from"fs";import Zn from"path";async function eo(e,t){let o=`# Automatically injected by create-sailor
1636
1636
  DATABASE_URL="${String(t.databaseUrl)}"
1637
1637
 
1638
1638
  NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="${String(t.clerkPublishable)}"
1639
1639
  CLERK_SECRET_KEY="${String(t.clerkSecret)}"
1640
1640
 
1641
1641
  NEXT_PUBLIC_SITE_URL="http://localhost:3000"
1642
- `,n=Jn.join(e,".env"),r=Jn.join(e,".env.local");!Ut.existsSync(n)&&!Ut.existsSync(r)?Ut.writeFileSync(r,o):Ut.appendFileSync(r,`
1643
- `+o)}import eo from"crypto";import mt from"fs";import Zn from"path";function Re(e){return eo.randomBytes(e).toString("base64").replace(/=+$/,"")}function $s(e){return eo.randomBytes(e).toString("hex")}function Ys(){return{AUTH_SECRET:Re(32),NEXTAUTH_SECRET:Re(32),BETTER_AUTH_SECRET:Re(32),JWT_SECRET:Re(32),WEBHOOK_SECRET:$s(16),ENCRYPTION_KEY:Re(32),API_SECRET_KEY:Re(32),SESSION_SECRET:Re(32)}}function qs(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Gs(e,t,o){let n=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=qs(o);return e.replace(n,`${t}="${r}"`)}async function to(e){let t=Zn.join(e,".env.example"),o=Zn.join(e,".env.local");if(!mt.existsSync(t))return null;try{let n=mt.readFileSync(t,"utf8"),r=Ys(),i=mt.existsSync(o)?mt.readFileSync(o,"utf8"):n;for(let c of Object.keys(r))i=Gs(i,c,r[c]);return mt.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 Lt=[{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 no(e){return Lt.find(t=>t.id===e)}var Qc=Lt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function oo(e,t,o="global"){let n=no(t);if(!n)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${Lt.map(r=>r.id).join(", ")}`);if(n.id==="none"){G(e,"feature-flags");return}n.envVars.length>0&&Q(e,{category:"Feature Flags",name:n.name,envVars:n.envVars,docs:n.docs}),Z(e,"FEATURE_FLAGS_PROVIDER",n.id)}import{execFileSync as io}from"child_process";import L from"fs";import Hs from"os";import le from"path";import Ws from"ignore";var Xs={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 zs(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function Js(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function ao(e){return/^[0-9a-f]{7,40}$/i.test(e)}function Qs(e,t){let o=`https://github.com/${e}.git`,n=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of n)try{let s=io("git",["ls-remote",o,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!s)continue;let[i]=s.split(/\s+/);if(ao(i))return i}catch{}return null}async function Zs(e,t){if(ao(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=Qs(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 co(e,t,o){let n=L.readdirSync(t,{withFileTypes:!0});for(let r of n){if(r.name==="node_modules"||r.name===".git")continue;let s=le.join(t,r.name),i=le.relative(e,s).split(le.sep).join("/");r.isDirectory()?(o.push(i+"/"),co(e,s,o)):o.push(i)}}function ei(e){let t=le.join(e,".templateignore");if(!L.existsSync(t))return;let o=L.readFileSync(t,"utf8"),n=Ws().add(o),r=[];co(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=le.join(e,a);try{L.existsSync(l)&&L.rmSync(l,{recursive:!0,force:!0})}catch{}}try{L.existsSync(t)&&L.rmSync(t,{force:!0})}catch{}}async function ro(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)`);L.writeFileSync(t,n);let r=L.statSync(t);if(r.size!==n.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${n.byteLength})`);return r.size}function so(e,t){io("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function po(e){try{let t=L.readdirSync(e);for(let o of t)L.rmSync(le.join(e,o),{recursive:!0,force:!0})}catch{}}async function ti(e,t){let o=L.mkdtempSync(le.join(Hs.tmpdir(),"create-sailor-")),n=le.join(o,"template.tar.gz");try{let r=await Zs(e.repo,e.ref);await ro(Js(e.repo,r),n),so(n,t)}catch(r){if(!e.allowMutableFallback)throw r;po(t),await ro(zs(e.repo,e.ref),n),so(n,t)}finally{L.rmSync(o,{recursive:!0,force:!0})}}async function lo(e){L.mkdirSync(e,{recursive:!0});let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],n;for(let r of o){let s=Xs[r];try{if(await ti(s,e),s.applyIgnore)try{ei(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)),po(e)}}throw new Error(`Failed to download the template from any source. Last error: ${n?.message??"unknown"}
1642
+ `,n=Zn.join(e,".env"),r=Zn.join(e,".env.local");!Lt.existsSync(n)&&!Lt.existsSync(r)?Lt.writeFileSync(r,o):Lt.appendFileSync(r,`
1643
+ `+o)}import no from"crypto";import gt from"fs";import to from"path";function Re(e){return no.randomBytes(e).toString("base64").replace(/=+$/,"")}function Ws(e){return no.randomBytes(e).toString("hex")}function Xs(){return{AUTH_SECRET:Re(32),NEXTAUTH_SECRET:Re(32),BETTER_AUTH_SECRET:Re(32),JWT_SECRET:Re(32),WEBHOOK_SECRET:Ws(16),ENCRYPTION_KEY:Re(32),API_SECRET_KEY:Re(32),SESSION_SECRET:Re(32)}}function zs(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Js(e,t,o){let n=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=zs(o);return e.replace(n,`${t}="${r}"`)}async function oo(e){let t=to.join(e,".env.example"),o=to.join(e,".env.local");if(!gt.existsSync(t))return null;try{let n=gt.readFileSync(t,"utf8"),r=Xs(),i=gt.existsSync(o)?gt.readFileSync(o,"utf8"):n;for(let c of Object.keys(r))i=Js(i,c,r[c]);return gt.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 Mt=[{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 ro(e){return Mt.find(t=>t.id===e)}var ip=Mt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function so(e,t,o="global"){let n=ro(t);if(!n)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${Mt.map(r=>r.id).join(", ")}`);if(n.id==="none"){H(e,"feature-flags");return}n.envVars.length>0&&Q(e,{category:"Feature Flags",name:n.name,envVars:n.envVars,docs:n.docs}),Z(e,"FEATURE_FLAGS_PROVIDER",n.id)}import{execFileSync as co}from"child_process";import L from"fs";import Qs from"os";import le from"path";import Zs from"ignore";var ei={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 ti(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function ni(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function po(e){return/^[0-9a-f]{7,40}$/i.test(e)}function oi(e,t){let o=`https://github.com/${e}.git`,n=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of n)try{let s=co("git",["ls-remote",o,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!s)continue;let[i]=s.split(/\s+/);if(po(i))return i}catch{}return null}async function ri(e,t){if(po(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=oi(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 lo(e,t,o){let n=L.readdirSync(t,{withFileTypes:!0});for(let r of n){if(r.name==="node_modules"||r.name===".git")continue;let s=le.join(t,r.name),i=le.relative(e,s).split(le.sep).join("/");r.isDirectory()?(o.push(i+"/"),lo(e,s,o)):o.push(i)}}function si(e){let t=le.join(e,".templateignore");if(!L.existsSync(t))return;let o=L.readFileSync(t,"utf8"),n=Zs().add(o),r=[];lo(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=le.join(e,a);try{L.existsSync(l)&&L.rmSync(l,{recursive:!0,force:!0})}catch{}}try{L.existsSync(t)&&L.rmSync(t,{force:!0})}catch{}}async function io(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)`);L.writeFileSync(t,n);let r=L.statSync(t);if(r.size!==n.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${n.byteLength})`);return r.size}function ao(e,t){co("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function uo(e){try{let t=L.readdirSync(e);for(let o of t)L.rmSync(le.join(e,o),{recursive:!0,force:!0})}catch{}}async function ii(e,t){let o=L.mkdtempSync(le.join(Qs.tmpdir(),"create-sailor-")),n=le.join(o,"template.tar.gz");try{let r=await ri(e.repo,e.ref);await io(ni(e.repo,r),n),ao(n,t)}catch(r){if(!e.allowMutableFallback)throw r;uo(t),await io(ti(e.repo,e.ref),n),ao(n,t)}finally{L.rmSync(o,{recursive:!0,force:!0})}}async function mo(e){L.mkdirSync(e,{recursive:!0});let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],n;for(let r of o){let s=ei[r];try{if(await ii(s,e),s.applyIgnore)try{si(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)),uo(e)}}throw new Error(`Failed to download the template from any source. Last error: ${n?.message??"unknown"}
1644
1644
 
1645
1645
  Ensure you have internet access and 'tar' installed.
1646
- You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import ke from"fs";import Zt from"path";async function uo(e,t){let o=Zt.join(e,"packages","mcp");if(t==="off"){ke.existsSync(o)&&ke.rmSync(o,{recursive:!0,force:!0});let r=Zt.join(e,"packages","cli","src","commands","mcp-server.ts");ke.existsSync(r)&&ke.rmSync(r,{force:!0});return}let n=Zt.join(e,".env.example");if(ke.existsSync(n)){let r=ke.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(`
1647
- `);ke.appendFileSync(n,i)}}}import gt from"fs";import mo from"path";async function go(e,t,o){let n=mo.join(e,"packages","metering"),r;if(t==="auto"?r=o!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){gt.existsSync(n)&&gt.rmSync(n,{recursive:!0,force:!0});return}let s=mo.join(e,".env.example");if(!gt.existsSync(s))return;let i=gt.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(`
1648
- `);gt.appendFileSync(s,a)}}import re from"fs";import M from"path";var fo=[{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:""}],fp=fo.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function yo(e){return fo.find(t=>t.id===e)}var en={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 ni(e){re.mkdirSync(e,{recursive:!0})}function tn(e,t){let o=M.join(e,"package.json");if(!re.existsSync(o))return;let n;try{n=JSON.parse(re.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};re.writeFileSync(o,JSON.stringify(i,null,2)+`
1649
- `)}function te(e,t){ni(M.dirname(e)),re.writeFileSync(e,t)}function ft(e,t){let o=M.join(e,".env.example");re.existsSync(o)?re.appendFileSync(o,`
1650
- `+t):re.writeFileSync(o,t)}function oi(e){let t=`import * as Sentry from "@sentry/nextjs";
1646
+ You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import ke from"fs";import tn from"path";async function go(e,t){let o=tn.join(e,"packages","mcp");if(t==="off"){ke.existsSync(o)&&ke.rmSync(o,{recursive:!0,force:!0});let r=tn.join(e,"packages","cli","src","commands","mcp-server.ts");ke.existsSync(r)&&ke.rmSync(r,{force:!0});return}let n=tn.join(e,".env.example");if(ke.existsSync(n)){let r=ke.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(`
1647
+ `);ke.appendFileSync(n,i)}}}import ft from"fs";import fo from"path";async function yo(e,t,o){let n=fo.join(e,"packages","metering"),r;if(t==="auto"?r=o!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){ft.existsSync(n)&&ft.rmSync(n,{recursive:!0,force:!0});return}let s=fo.join(e,".env.example");if(!ft.existsSync(s))return;let i=ft.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(`
1648
+ `);ft.appendFileSync(s,a)}}import re from"fs";import M from"path";var So=[{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:""}],Pp=So.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function ho(e){return So.find(t=>t.id===e)}var nn={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 ai(e){re.mkdirSync(e,{recursive:!0})}function on(e,t){let o=M.join(e,"package.json");if(!re.existsSync(o))return;let n;try{n=JSON.parse(re.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};re.writeFileSync(o,JSON.stringify(i,null,2)+`
1649
+ `)}function te(e,t){ai(M.dirname(e)),re.writeFileSync(e,t)}function yt(e,t){let o=M.join(e,".env.example");re.existsSync(o)?re.appendFileSync(o,`
1650
+ `+t):re.writeFileSync(o,t)}function ci(e){let t=`import * as Sentry from "@sentry/nextjs";
1651
1651
 
1652
1652
  Sentry.init({
1653
1653
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
@@ -1690,14 +1690,14 @@ export async function register() {
1690
1690
  }
1691
1691
 
1692
1692
  export { captureRequestError as onRequestError } from "@sentry/nextjs";
1693
- `;te(M.join(e,"sentry.client.config.ts"),t),te(M.join(e,"sentry.server.config.ts"),o),te(M.join(e,"sentry.edge.config.ts"),n),te(M.join(e,"instrumentation.ts"),r)}function ri(){return`# Sentry \u2014 error tracking + performance monitoring
1693
+ `;te(M.join(e,"sentry.client.config.ts"),t),te(M.join(e,"sentry.server.config.ts"),o),te(M.join(e,"sentry.edge.config.ts"),n),te(M.join(e,"instrumentation.ts"),r)}function pi(){return`# Sentry \u2014 error tracking + performance monitoring
1694
1694
  # Get your DSN from https://sentry.io/settings/projects/<project>/keys/
1695
1695
  SENTRY_DSN=
1696
1696
  NEXT_PUBLIC_SENTRY_DSN=
1697
1697
  SENTRY_ORG=
1698
1698
  SENTRY_PROJECT=
1699
1699
  SENTRY_AUTH_TOKEN=
1700
- `}function si(e){let t=`/**
1700
+ `}function li(e){let t=`/**
1701
1701
  * Next.js instrumentation hook \u2014 wires Datadog APM (dd-trace) into Node runtime.
1702
1702
  * Edge runtime is not supported by dd-trace; only nodejs is initialized.
1703
1703
  */
@@ -1745,7 +1745,7 @@ export function initDatadogRum(): void {
1745
1745
  });
1746
1746
  initialized = true;
1747
1747
  }
1748
- `;te(M.join(e,"instrumentation.ts"),t),te(M.join(e,"src","lib","monitoring","datadog-rum.ts"),o)}function ii(){return`# Datadog \u2014 APM + RUM
1748
+ `;te(M.join(e,"instrumentation.ts"),t),te(M.join(e,"src","lib","monitoring","datadog-rum.ts"),o)}function di(){return`# Datadog \u2014 APM + RUM
1749
1749
  # Server APM (dd-trace)
1750
1750
  DD_API_KEY=
1751
1751
  DD_APP_KEY=
@@ -1760,7 +1760,7 @@ NEXT_PUBLIC_DD_SITE=datadoghq.com
1760
1760
  NEXT_PUBLIC_DD_SERVICE=sailor-web
1761
1761
  NEXT_PUBLIC_DD_ENV=production
1762
1762
  NEXT_PUBLIC_DD_VERSION=
1763
- `}function ai(e){let t=`/**
1763
+ `}function ui(e){let t=`/**
1764
1764
  * Bugsnag server-side initialization.
1765
1765
  * Import this once at the top of your server entrypoint or a shared init module.
1766
1766
  */
@@ -1809,11 +1809,11 @@ export function getBugsnagErrorBoundary() {
1809
1809
  errorBoundary = plugin.createErrorBoundary(React) as typeof errorBoundary;
1810
1810
  return errorBoundary;
1811
1811
  }
1812
- `;te(M.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),te(M.join(e,"src","lib","monitoring","bugsnag.client.tsx"),o)}function ci(){return`# Bugsnag \u2014 error tracking
1812
+ `;te(M.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),te(M.join(e,"src","lib","monitoring","bugsnag.client.tsx"),o)}function mi(){return`# Bugsnag \u2014 error tracking
1813
1813
  BUGSNAG_API_KEY=
1814
1814
  NEXT_PUBLIC_BUGSNAG_API_KEY=
1815
1815
  APP_VERSION=
1816
- `}function pi(e){te(M.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1816
+ `}function gi(e){te(M.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1817
1817
  /**
1818
1818
  * \u963F\u91CC\u4E91 ARMS (Application Real-time Monitoring Service) browser agent.
1819
1819
  * Injects the official JS agent via next/script.
@@ -1834,11 +1834,11 @@ export function ArmsScript() {
1834
1834
  />
1835
1835
  );
1836
1836
  }
1837
- `)}function li(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1837
+ `)}function fi(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1838
1838
  ALIYUN_ARMS_LICENSE_KEY=
1839
1839
  ALIYUN_ARMS_APP_NAME=
1840
1840
  NEXT_PUBLIC_ARMS_PID=
1841
- `}function di(e){te(M.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1841
+ `}function yi(e){te(M.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1842
1842
  /**
1843
1843
  * \u542C\u4E91 Browser Agent (\u524D\u7AEF\u6027\u80FD\u76D1\u63A7).
1844
1844
  * Docs: https://www.tingyun.com/docs
@@ -1856,12 +1856,12 @@ export function TingYunScript() {
1856
1856
  />
1857
1857
  );
1858
1858
  }
1859
- `)}function ui(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1859
+ `)}function Si(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1860
1860
  TINGYUN_LICENSE_KEY=
1861
1861
  NEXT_PUBLIC_TINGYUN_APP_KEY=
1862
- `}async function So(e,t,o="global"){let n=yo(t);if(!n||n.id==="none")return;let r=M.join(e,"apps","web");if(!re.existsSync(r))return;let s=n.id;try{switch(s){case"sentry":oi(r),tn(r,en.sentry),ft(e,ri());return;case"datadog":si(r),tn(r,en.datadog),ft(e,ii());return;case"bugsnag":ai(r),tn(r,en.bugsnag),ft(e,ci());return;case"aliyun-arms":pi(r),ft(e,li());return;case"tingyun":di(r),ft(e,ui());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 Mt=[{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 ho(e){return Mt.find(t=>t.id===e)}var _p=Mt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Eo(e,t,o="global"){let n=ho(t);if(!n)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${Mt.map(r=>r.id).join(", ")}`);if(n.id==="none"){G(e,"notifications");return}n.envVars.length>0&&Q(e,{category:"Notifications",name:n.name,envVars:n.envVars,docs:n.docs}),Z(e,"NOTIFICATIONS_PROVIDER",n.id)}import nn from"fs";import mi from"path";async function vo(e,t){let o=mi.join(e,"package.json");if(nn.existsSync(o)){let n=nn.readFileSync(o,"utf8"),r=JSON.parse(n);r.name=t,r.version="0.1.0",nn.writeFileSync(o,JSON.stringify(r,null,2)+`
1863
- `)}}import se from"fs";import yt from"path";var gi=["stripe","lemonsqueezy","chinapay","polar"];function _o(e){se.existsSync(e)&&se.rmSync(e,{recursive:!0,force:!0})}function fi(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function yi(e,t){let o=yt.join(e,".env.example");se.existsSync(o)?se.appendFileSync(o,`
1864
- `+t):se.writeFileSync(o,t)}function Si(e){switch(e){case"stripe":return`# Stripe
1862
+ `}async function Eo(e,t,o="global"){let n=ho(t);if(!n||n.id==="none")return;let r=M.join(e,"apps","web");if(!re.existsSync(r))return;let s=n.id;try{switch(s){case"sentry":ci(r),on(r,nn.sentry),yt(e,pi());return;case"datadog":li(r),on(r,nn.datadog),yt(e,di());return;case"bugsnag":ui(r),on(r,nn.bugsnag),yt(e,mi());return;case"aliyun-arms":gi(r),yt(e,fi());return;case"tingyun":yi(r),yt(e,Si());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 Dt=[{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 vo(e){return Dt.find(t=>t.id===e)}var kp=Dt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function _o(e,t,o="global"){let n=vo(t);if(!n)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${Dt.map(r=>r.id).join(", ")}`);if(n.id==="none"){H(e,"notifications");return}n.envVars.length>0&&Q(e,{category:"Notifications",name:n.name,envVars:n.envVars,docs:n.docs}),Z(e,"NOTIFICATIONS_PROVIDER",n.id)}import rn from"fs";import hi from"path";async function bo(e,t){let o=hi.join(e,"package.json");if(rn.existsSync(o)){let n=rn.readFileSync(o,"utf8"),r=JSON.parse(n);r.name=t,r.version="0.1.0",rn.writeFileSync(o,JSON.stringify(r,null,2)+`
1863
+ `)}}import Ft from"fs";import nt from"path";import{fileURLToPath as Ei}from"url";var vi=Ei(import.meta.url),Po=nt.dirname(vi);function _i(){let e=[nt.join(Po,"..","templates","orm","drizzle"),nt.join(Po,"..","..","templates","orm","drizzle")];for(let t of e)if(Ft.existsSync(t))return t;return null}function Co(e,t){Ft.mkdirSync(t,{recursive:!0});for(let o of Ft.readdirSync(e,{withFileTypes:!0})){let n=nt.join(e,o.name),r=nt.join(t,o.name);o.isDirectory()?Co(n,r):Ft.copyFileSync(n,r)}}async function Io(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=_i();if(!n)return{applied:!1,reason:"Drizzle template directory not found in package \u2014 bundling error"};let r=nt.join(e,"packages","platform","db-drizzle");return Co(n,r),{applied:!0}}import se from"fs";import St from"path";var bi=["stripe","lemonsqueezy","chinapay","polar"];function Ao(e){se.existsSync(e)&&se.rmSync(e,{recursive:!0,force:!0})}function Pi(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function Ci(e,t){let o=St.join(e,".env.example");se.existsSync(o)?se.appendFileSync(o,`
1864
+ `+t):se.writeFileSync(o,t)}function Ii(e){switch(e){case"stripe":return`# Stripe
1865
1865
  STRIPE_SECRET_KEY=
1866
1866
  STRIPE_WEBHOOK_SECRET=
1867
1867
  `;case"lemon":return`# Lemon Squeezy
@@ -1876,13 +1876,13 @@ CHINAPAY_WECHAT_ENABLED=true
1876
1876
  CHINAPAY_APP_ID=
1877
1877
  CHINAPAY_APP_SECRET=
1878
1878
  CHINAPAY_ALIPAY_ENABLED=true
1879
- `}}async function bo(e,t){let o=yt.join(e,"packages","commerce","billing");if(!se.existsSync(o))return;if(t==="none"){_o(o);return}let n=yt.join(o,"src"),r=new Set(fi(t));for(let i of gi)r.has(i)||_o(yt.join(n,i));let s=yt.join(n,"checkout","types.ts");if(se.existsSync(s)){let i=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",c=se.readFileSync(s,"utf8"),a=c.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${i}";`);a!==c&&se.writeFileSync(s,a)}yi(e,Si(t))}import de from"fs";import tt from"path";var Io=new Set(["siliconflow","volcengine-ark","bailian","moonshot"]),on=/@sailor:([^\s*]+)/;function hi(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=>Io.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 Po(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function Co(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function Ao(e,t){let o=e.split(`
1880
- `),n=[],r=e.includes("#"),s=0;for(;s<o.length;){let i=o[s],c=i.match(on);if(!c){n.push(i),s++;continue}let{marker:a,keep:l}=hi(c[1],t);if(a==="registry-entries"){n.push(r?Co(i):Po(i)),s++;continue}if(l){let m=r?Co(i):Po(i);m.trim().length>0&&n.push(m);let S=s+1;for(;S<o.length&&o[S].trim()!==""&&!on.test(o[S]);)n.push(o[S]),S++;S<o.length&&o[S].trim()===""&&(n.push(o[S]),S++),s=S}else{let m=s+1;for(;m<o.length&&o[m].trim()!==""&&!on.test(o[m]);)m++;m<o.length&&o[m].trim()===""&&m++,s=m}}return Ei(n.join(`
1881
- `),t)}function Ei(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(`
1879
+ `}}async function wo(e,t){let o=St.join(e,"packages","commerce","billing");if(!se.existsSync(o))return;if(t==="none"){Ao(o);return}let n=St.join(o,"src"),r=new Set(Pi(t));for(let i of bi)r.has(i)||Ao(St.join(n,i));let s=St.join(n,"checkout","types.ts");if(se.existsSync(s)){let i=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",c=se.readFileSync(s,"utf8"),a=c.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${i}";`);a!==c&&se.writeFileSync(s,a)}Ci(e,Ii(t))}import de from"fs";import ot from"path";var xo=new Set(["siliconflow","volcengine-ark","bailian","moonshot"]),sn=/@sailor:([^\s*]+)/;function Ai(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=>xo.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 Ro(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function ko(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function To(e,t){let o=e.split(`
1880
+ `),n=[],r=e.includes("#"),s=0;for(;s<o.length;){let i=o[s],c=i.match(sn);if(!c){n.push(i),s++;continue}let{marker:a,keep:l}=Ai(c[1],t);if(a==="registry-entries"){n.push(r?ko(i):Ro(i)),s++;continue}if(l){let m=r?ko(i):Ro(i);m.trim().length>0&&n.push(m);let S=s+1;for(;S<o.length&&o[S].trim()!==""&&!sn.test(o[S]);)n.push(o[S]),S++;S<o.length&&o[S].trim()===""&&(n.push(o[S]),S++),s=S}else{let m=s+1;for(;m<o.length&&o[m].trim()!==""&&!sn.test(o[m]);)m++;m<o.length&&o[m].trim()===""&&m++,s=m}}return wi(n.join(`
1881
+ `),t)}function wi(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(`
1882
1882
  `).filter(l=>{let m=l.trim();if(m===""||m.startsWith("//"))return!0;let S=m.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return S?r.has(S[1]):!0}).join(`
1883
- `);return e.replace(s,`createProviderRegistry({${a}})`)}function vi(e,t){let o=tt.join(t,"registry.ts.template"),n=de.readFileSync(o,"utf-8");return Ao(n,e)}function _i(e,t){let o=tt.join(t,".env.example.template"),n=de.readFileSync(o,"utf-8");return Ao(n,e)}async function wo(e,t,o){let n=vi(t,o),r=_i(t,o),s=tt.join(e,"packages/ai/agents/src");await de.promises.mkdir(s,{recursive:!0}),await de.promises.writeFile(tt.join(s,"registry.ts"),n),await de.promises.appendFile(tt.join(e,".env.example"),`
1884
- `+r);let i={ai:"latest"},{providerIds:c,customEndpoint:a}=t;(c.includes("openai")||a||c.some(m=>Io.has(m)))&&(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=tt.join(e,"package.json");if(de.existsSync(l)){let m=JSON.parse(await de.promises.readFile(l,"utf-8"));m.dependencies||(m.dependencies={});for(let[S,N]of Object.entries(i))m.dependencies[S]=N;await de.promises.writeFile(l,JSON.stringify(m,null,2)+`
1885
- `)}}import f from"fs";import d from"path";function Ro(e,t){if(!f.existsSync(e))return;let o=f.readdirSync(e);for(let n of o){let r=d.join(e,n);f.statSync(r).isDirectory()?Ro(r,t):t(r)}}async function ko(e,t){let o=d.join(e,"package.json");if(!f.existsSync(o))return;let n=JSON.parse(f.readFileSync(o,"utf8"));if(t.orm!=="prisma"){let r=d.join(e,"packages","db");if(f.existsSync(r)){let s=d.join(r,"prisma");f.existsSync(s)&&f.rmSync(s,{recursive:!0,force:!0});let i=d.join(r,"package.json");if(f.existsSync(i)){let a=JSON.parse(f.readFileSync(i,"utf8"));a.dependencies&&delete a.dependencies["@prisma/client"],a.devDependencies&&delete a.devDependencies.prisma,f.writeFileSync(i,JSON.stringify(a,null,2)+`
1883
+ `);return e.replace(s,`createProviderRegistry({${a}})`)}function Ri(e,t){let o=ot.join(t,"registry.ts.template"),n=de.readFileSync(o,"utf-8");return To(n,e)}function ki(e,t){let o=ot.join(t,".env.example.template"),n=de.readFileSync(o,"utf-8");return To(n,e)}async function No(e,t,o){let n=Ri(t,o),r=ki(t,o),s=ot.join(e,"packages/ai/agents/src");await de.promises.mkdir(s,{recursive:!0}),await de.promises.writeFile(ot.join(s,"registry.ts"),n),await de.promises.appendFile(ot.join(e,".env.example"),`
1884
+ `+r);let i={ai:"latest"},{providerIds:c,customEndpoint:a}=t;(c.includes("openai")||a||c.some(m=>xo.has(m)))&&(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=ot.join(e,"package.json");if(de.existsSync(l)){let m=JSON.parse(await de.promises.readFile(l,"utf-8"));m.dependencies||(m.dependencies={});for(let[S,T]of Object.entries(i))m.dependencies[S]=T;await de.promises.writeFile(l,JSON.stringify(m,null,2)+`
1885
+ `)}}import f from"fs";import d from"path";function Oo(e,t){if(!f.existsSync(e))return;let o=f.readdirSync(e);for(let n of o){let r=d.join(e,n);f.statSync(r).isDirectory()?Oo(r,t):t(r)}}async function Uo(e,t){let o=d.join(e,"package.json");if(!f.existsSync(o))return;let n=JSON.parse(f.readFileSync(o,"utf8"));if(t.orm!=="prisma"){let r=d.join(e,"packages","db");if(f.existsSync(r)){let s=d.join(r,"prisma");f.existsSync(s)&&f.rmSync(s,{recursive:!0,force:!0});let i=d.join(r,"package.json");if(f.existsSync(i)){let a=JSON.parse(f.readFileSync(i,"utf8"));a.dependencies&&delete a.dependencies["@prisma/client"],a.devDependencies&&delete a.devDependencies.prisma,f.writeFileSync(i,JSON.stringify(a,null,2)+`
1886
1886
  `)}let c=d.join(r,"src","index.ts");f.existsSync(c)&&f.writeFileSync(c,`
1887
1887
  export const prisma = {} as any;
1888
1888
  export const db = {} as any;
@@ -1929,7 +1929,7 @@ export type UsageAggregate = any;
1929
1929
  export type UsageLedgerEntry = any;
1930
1930
  export type UsageType = any;
1931
1931
  export type UsageLedgerSource = any;
1932
- `)}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(f.existsSync(r)){let s=f.readdirSync(r);for(let i of s){let c=d.join(r,i);if(!f.statSync(c).isDirectory())continue;let a=d.join(c,"src","app");if(!f.existsSync(a))continue;["[lang]","[locale]"].forEach(b=>{let u=d.join(a,b);if(f.existsSync(u)){let U=f.readdirSync(u);for(let _t of U)f.renameSync(d.join(u,_t),d.join(a,_t));f.rmdirSync(u)}}),["src/middleware.ts","middleware.ts"].forEach(b=>{let u=d.join(c,b);f.existsSync(u)&&f.rmSync(u)});let l=d.join(c,"src","lib");f.existsSync(l)||f.mkdirSync(l,{recursive:!0});let m=d.join(l,"mock-i18n.ts");f.writeFileSync(m,`
1932
+ `)}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(f.existsSync(r)){let s=f.readdirSync(r);for(let i of s){let c=d.join(r,i);if(!f.statSync(c).isDirectory())continue;let a=d.join(c,"src","app");if(!f.existsSync(a))continue;["[lang]","[locale]"].forEach(b=>{let u=d.join(a,b);if(f.existsSync(u)){let U=f.readdirSync(u);for(let bt of U)f.renameSync(d.join(u,bt),d.join(a,bt));f.rmdirSync(u)}}),["src/middleware.ts","middleware.ts"].forEach(b=>{let u=d.join(c,b);f.existsSync(u)&&f.rmSync(u)});let l=d.join(c,"src","lib");f.existsSync(l)||f.mkdirSync(l,{recursive:!0});let m=d.join(l,"mock-i18n.ts");f.writeFileSync(m,`
1933
1933
  import React from 'react';
1934
1934
  export function useTranslations(namespace?: string): any { return (key: string) => key; }
1935
1935
  export function useLocale() { return 'en'; }
@@ -1947,7 +1947,7 @@ export const useRouter = () => ({ push: (...args: any[]) => {}, replace: (...arg
1947
1947
  export default function createMiddleware(...args: any[]) { return (req: any) => req; }
1948
1948
  export function createNavigation(...args: any[]) { return { Link, redirect, usePathname, useRouter, getPathname: () => '/' }; }
1949
1949
  export function defineRouting<T>(config: T): T { return config; }
1950
- `);let N=d.join(l,"mock-i18n.d.ts");f.writeFileSync(N,`declare module '@/lib/mock-i18n' {
1950
+ `);let T=d.join(l,"mock-i18n.d.ts");f.writeFileSync(T,`declare module '@/lib/mock-i18n' {
1951
1951
  export function useTranslations(namespace?: string): any;
1952
1952
  export function useLocale(): string;
1953
1953
  export const NextIntlClientProvider: React.FC<any>;
@@ -1968,16 +1968,16 @@ export function defineRouting<T>(config: T): T { return config; }
1968
1968
  `),f.writeFileSync(d.join(l,"mock-i18n-index.ts"),`
1969
1969
  export * from './mock-i18n';
1970
1970
  export { default } from './mock-i18n';
1971
- `);let T=d.join(c,"tsconfig.json");if(f.existsSync(T))try{let b=f.readFileSync(T,"utf8");if(b.includes('"paths": {')){let u=b.replace(/"paths":\s*\{/,`"paths": {
1971
+ `);let N=d.join(c,"tsconfig.json");if(f.existsSync(N))try{let b=f.readFileSync(N,"utf8");if(b.includes('"paths": {')){let u=b.replace(/"paths":\s*\{/,`"paths": {
1972
1972
  "next-intl": ["./src/lib/mock-i18n"],
1973
- "next-intl/*": ["./src/lib/mock-i18n"],`);f.writeFileSync(T,u)}}catch{}let D=d.join(c,"src");f.existsSync(D)&&Ro(D,b=>{if(!b.endsWith(".ts")&&!b.endsWith(".tsx"))return;let u=f.readFileSync(b,"utf8"),U=!1;b.endsWith("src/app/layout.tsx")&&u.includes("../providers")&&(u=u.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),U=!0),u=u.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),u=u.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),u.match(/locale\s*:\s*any/)&&(u=u.replace(/locale\s*:\s*any/g,"locale: string"),U=!0),u.match(/lang\s*:\s*any/)&&(u=u.replace(/lang\s*:\s*any/g,"lang: string"),U=!0),u.match(/requestLocale\s*:\s*any/)&&(u=u.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),U=!0),u.match(/\(locale\s*=\s*(.*)\)/)&&(u=u.replace(/\(locale\s*=\s*(.*)\)/g,"() "),U=!0),u.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(u=u.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"))&&(u=u.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),u=u.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),u=u.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),u=u.replace(/\(l\)\s*=>/g,"(l: any) =>"),U=!0),b.endsWith("src/i18n/request.ts")&&(u=u.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),U=!0),(u.match(/locale\s*:/)||u.match(/lang\s*:/))&&(U=!0),U&&f.writeFileSync(b,u)});let ie=d.join(c,"package.json");if(f.existsSync(ie)){let b=JSON.parse(f.readFileSync(ie,"utf8"));b.dependencies&&delete b.dependencies["next-intl"],f.writeFileSync(ie,JSON.stringify(b,null,2)+`
1973
+ "next-intl/*": ["./src/lib/mock-i18n"],`);f.writeFileSync(N,u)}}catch{}let D=d.join(c,"src");f.existsSync(D)&&Oo(D,b=>{if(!b.endsWith(".ts")&&!b.endsWith(".tsx"))return;let u=f.readFileSync(b,"utf8"),U=!1;b.endsWith("src/app/layout.tsx")&&u.includes("../providers")&&(u=u.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),U=!0),u=u.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),u=u.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),u.match(/locale\s*:\s*any/)&&(u=u.replace(/locale\s*:\s*any/g,"locale: string"),U=!0),u.match(/lang\s*:\s*any/)&&(u=u.replace(/lang\s*:\s*any/g,"lang: string"),U=!0),u.match(/requestLocale\s*:\s*any/)&&(u=u.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),U=!0),u.match(/\(locale\s*=\s*(.*)\)/)&&(u=u.replace(/\(locale\s*=\s*(.*)\)/g,"() "),U=!0),u.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(u=u.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"))&&(u=u.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),u=u.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),u=u.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),u=u.replace(/\(l\)\s*=>/g,"(l: any) =>"),U=!0),b.endsWith("src/i18n/request.ts")&&(u=u.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),U=!0),(u.match(/locale\s*:/)||u.match(/lang\s*:/))&&(U=!0),U&&f.writeFileSync(b,u)});let ie=d.join(c,"package.json");if(f.existsSync(ie)){let b=JSON.parse(f.readFileSync(ie,"utf8"));b.dependencies&&delete b.dependencies["next-intl"],f.writeFileSync(ie,JSON.stringify(b,null,2)+`
1974
1974
  `)}}}}f.writeFileSync(o,JSON.stringify(n,null,2)+`
1975
- `)}function _(e){try{f.rmSync(e,{recursive:!0,force:!0})}catch{}}function bi(e,t){if(!f.existsSync(e))return;let o;try{o=JSON.parse(f.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&&f.writeFileSync(e,JSON.stringify(o,null,2)+`
1976
- `)}function xo(e,t){t.cronJobs||(_(d.join(e,"apps/web/src/app/api/cron")),_(d.join(e,"packages/integrations/queue/src/scheduled"))),t.auditLog||(_(d.join(e,"apps/web/src/app/[locale]/(app)/settings/audit-log")),_(d.join(e,"apps/web/src/app/api/audit-logs")),_(d.join(e,"apps/web/src/components/audit"))),t.apiKeys||(_(d.join(e,"apps/web/src/app/[locale]/(app)/settings/api-keys")),_(d.join(e,"apps/web/src/app/api/api-keys")),_(d.join(e,"apps/web/src/components/api-keys"))),t.webhooks||(_(d.join(e,"apps/web/src/app/[locale]/(app)/settings/webhooks")),_(d.join(e,"apps/web/src/app/api/webhooks")),_(d.join(e,"apps/web/src/components/webhooks")),_(d.join(e,"packages/webhooks"))),t.commandPalette||(_(d.join(e,"apps/web/src/components/command-palette")),_(d.join(e,"apps/web/src/app/[locale]/providers/command-palette-mount.tsx"))),t.cookieConsent||(_(d.join(e,"apps/landing-page/src/components/cookie-consent-banner.tsx")),_(d.join(e,"apps/landing-page/src/components/__tests__/cookie-consent-banner.test.tsx")),_(d.join(e,"apps/landing-page/src/lib/cookie-consent.ts")),_(d.join(e,"apps/landing-page/src/lib/__tests__/cookie-consent.test.ts")),_(d.join(e,"apps/web/src/app/api/cookie-consent"))),t.legalPages||(_(d.join(e,"apps/landing-page/src/app/[lang]/(legal)/legal")),_(d.join(e,"apps/landing-page/src/lib/legal-documents.ts")),_(d.join(e,"apps/landing-page/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(_(d.join(e,"packages/china-compliance")),_(d.join(e,"apps/landing-page/src/components/icp-footer.tsx")),_(d.join(e,"apps/landing-page/src/components/__tests__/icp-footer.test.tsx")),_(d.join(e,"apps/web/src/components/auth/wechat-login-button.tsx")),_(d.join(e,"apps/web/src/components/auth/__tests__/wechat-login-button.test.tsx")),bi(d.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import{getSchema as Pi,printSchema as Ci}from"@mrleebo/prisma-ast";var Ii=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function Ai(e){return e.type==="comment"&&e.text.trim().startsWith("///")}function wi(e){let t=Ii.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 Ri(e,t){for(let o=t-1;o>=0;o--){let n=e[o];if(n.type==="comment"){let r=wi(n.text);if(r)return{annIndex:o,parsed:r};continue}break}return null}function rn(e,t){let o=Pi(e),n=new Set;for(let c=0;c<o.list.length;c++){if(o.list[c].type!=="model")continue;let l=Ri(o.list,c);if(!l)continue;let m=t[l.parsed.flag];if(m!==void 0&&l.parsed.values.includes(m))n.add(l.annIndex);else{n.add(c);for(let T=c-1;T>=0;T--){let D=o.list[T];if(D.type==="comment"&&Ai(D)){n.add(T);continue}break}let N=o.list[c+1];N&&N.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 Ci({type:"schema",list:s})}import nt from"fs";import To from"path";var Dt=[{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 No(e){return Dt.find(t=>t.id===e)}var Vp=Dt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Oo(e){return nt.existsSync(e)?nt.readFileSync(e,"utf-8"):null}function ki(e,t){let o=To.join(e,".env.example"),n=Oo(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(`
1977
- `);nt.appendFileSync(o,s)}function xi(e,t,o){let n=To.join(e,".env.example"),r=Oo(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?nt.writeFileSync(n,r.replace(s,`${t}="${o}"`)):nt.appendFileSync(n,`${t}="${o}"
1978
- `)}async function Uo(e,t,o){let n=be(e,"queue");if(t==="none"){n&&nt.rmSync(n,{recursive:!0,force:!0});return}let r=No(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${Dt.map(s=>s.id).join(", ")}`);n&&(ki(e,r),xi(e,"QUEUE_PROVIDER",t))}import ot from"fs";import Mo from"path";var Ft=[{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 Lo(e){return Ft.find(t=>t.id===e)}var Hp=Ft.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Do(e){return ot.existsSync(e)?ot.readFileSync(e,"utf-8"):null}function Ni(e,t){let o=Mo.join(e,".env.example"),n=Do(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(`
1979
- `);ot.appendFileSync(o,s)}function Ti(e,t,o){let n=Mo.join(e,".env.example"),r=Do(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?ot.writeFileSync(n,r.replace(s,`${t}="${o}"`)):ot.appendFileSync(n,`${t}="${o}"
1980
- `)}async function Fo(e,t,o){let n=be(e,"search");if(t==="none"){n&&ot.rmSync(n,{recursive:!0,force:!0});return}let r=Lo(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${Ft.map(s=>s.id).join(", ")}`);n&&(Ni(e,r),Ti(e,"SEARCH_PROVIDER",t))}import ue from"fs";import xe from"path";function Oi(e){let t=[xe.join(e,"packages","db"),xe.join(e,"apps","web")];for(let o of t){let n=xe.join(o,"prisma","schema.prisma");if(ue.existsSync(n))return{packageDir:o,seedPath:xe.join(o,"prisma","seed.ts"),packageJsonPath:xe.join(o,"package.json")}}return null}function Ui(e){try{let t=ue.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 Li(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
1975
+ `)}function _(e){try{f.rmSync(e,{recursive:!0,force:!0})}catch{}}function xi(e,t){if(!f.existsSync(e))return;let o;try{o=JSON.parse(f.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&&f.writeFileSync(e,JSON.stringify(o,null,2)+`
1976
+ `)}function Lo(e,t){t.cronJobs||(_(d.join(e,"apps/web/src/app/api/cron")),_(d.join(e,"packages/integrations/queue/src/scheduled"))),t.auditLog||(_(d.join(e,"apps/web/src/app/[locale]/(app)/settings/audit-log")),_(d.join(e,"apps/web/src/app/api/audit-logs")),_(d.join(e,"apps/web/src/components/audit"))),t.apiKeys||(_(d.join(e,"apps/web/src/app/[locale]/(app)/settings/api-keys")),_(d.join(e,"apps/web/src/app/api/api-keys")),_(d.join(e,"apps/web/src/components/api-keys"))),t.webhooks||(_(d.join(e,"apps/web/src/app/[locale]/(app)/settings/webhooks")),_(d.join(e,"apps/web/src/app/api/webhooks")),_(d.join(e,"apps/web/src/components/webhooks")),_(d.join(e,"packages/webhooks"))),t.commandPalette||(_(d.join(e,"apps/web/src/components/command-palette")),_(d.join(e,"apps/web/src/app/[locale]/providers/command-palette-mount.tsx"))),t.cookieConsent||(_(d.join(e,"apps/landing-page/src/components/cookie-consent-banner.tsx")),_(d.join(e,"apps/landing-page/src/components/__tests__/cookie-consent-banner.test.tsx")),_(d.join(e,"apps/landing-page/src/lib/cookie-consent.ts")),_(d.join(e,"apps/landing-page/src/lib/__tests__/cookie-consent.test.ts")),_(d.join(e,"apps/web/src/app/api/cookie-consent"))),t.legalPages||(_(d.join(e,"apps/landing-page/src/app/[lang]/(legal)/legal")),_(d.join(e,"apps/landing-page/src/lib/legal-documents.ts")),_(d.join(e,"apps/landing-page/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(_(d.join(e,"packages/china-compliance")),_(d.join(e,"apps/landing-page/src/components/icp-footer.tsx")),_(d.join(e,"apps/landing-page/src/components/__tests__/icp-footer.test.tsx")),_(d.join(e,"apps/web/src/components/auth/wechat-login-button.tsx")),_(d.join(e,"apps/web/src/components/auth/__tests__/wechat-login-button.test.tsx")),xi(d.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import{getSchema as Ti,printSchema as Ni}from"@mrleebo/prisma-ast";var Oi=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function Ui(e){return e.type==="comment"&&e.text.trim().startsWith("///")}function Li(e){let t=Oi.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 Mi(e,t){for(let o=t-1;o>=0;o--){let n=e[o];if(n.type==="comment"){let r=Li(n.text);if(r)return{annIndex:o,parsed:r};continue}break}return null}function an(e,t){let o=Ti(e),n=new Set;for(let c=0;c<o.list.length;c++){if(o.list[c].type!=="model")continue;let l=Mi(o.list,c);if(!l)continue;let m=t[l.parsed.flag];if(m!==void 0&&l.parsed.values.includes(m))n.add(l.annIndex);else{n.add(c);for(let N=c-1;N>=0;N--){let D=o.list[N];if(D.type==="comment"&&Ui(D)){n.add(N);continue}break}let T=o.list[c+1];T&&T.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 Ni({type:"schema",list:s})}import rt from"fs";import Do from"path";var jt=[{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 Mo(e){return jt.find(t=>t.id===e)}var Qp=jt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Fo(e){return rt.existsSync(e)?rt.readFileSync(e,"utf-8"):null}function Di(e,t){let o=Do.join(e,".env.example"),n=Fo(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(`
1977
+ `);rt.appendFileSync(o,s)}function Fi(e,t,o){let n=Do.join(e,".env.example"),r=Fo(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?rt.writeFileSync(n,r.replace(s,`${t}="${o}"`)):rt.appendFileSync(n,`${t}="${o}"
1978
+ `)}async function jo(e,t,o){let n=be(e,"queue");if(t==="none"){n&&rt.rmSync(n,{recursive:!0,force:!0});return}let r=Mo(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${jt.map(s=>s.id).join(", ")}`);n&&(Di(e,r),Fi(e,"QUEUE_PROVIDER",t))}import st from"fs";import Ko from"path";var Vt=[{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 Vo(e){return Vt.find(t=>t.id===e)}var sl=Vt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Bo(e){return st.existsSync(e)?st.readFileSync(e,"utf-8"):null}function ji(e,t){let o=Ko.join(e,".env.example"),n=Bo(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(`
1979
+ `);st.appendFileSync(o,s)}function Vi(e,t,o){let n=Ko.join(e,".env.example"),r=Bo(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?st.writeFileSync(n,r.replace(s,`${t}="${o}"`)):st.appendFileSync(n,`${t}="${o}"
1980
+ `)}async function $o(e,t,o){let n=be(e,"search");if(t==="none"){n&&st.rmSync(n,{recursive:!0,force:!0});return}let r=Vo(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${Vt.map(s=>s.id).join(", ")}`);n&&(ji(e,r),Vi(e,"SEARCH_PROVIDER",t))}import ue from"fs";import xe from"path";function Ki(e){let t=[xe.join(e,"packages","db"),xe.join(e,"apps","web")];for(let o of t){let n=xe.join(o,"prisma","schema.prisma");if(ue.existsSync(n))return{packageDir:o,seedPath:xe.join(o,"prisma","seed.ts"),packageJsonPath:xe.join(o,"package.json")}}return null}function Bi(e){try{let t=ue.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 $i(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
1981
1981
  const admin = await prisma.user.create({
1982
1982
  data: {
1983
1983
  clerkId: "user_mock_admin",
@@ -2008,7 +2008,7 @@ export { default } from './mock-i18n';
2008
2008
  console.log("\\u2713 Created admin user:", admin.email);
2009
2009
  } catch (err) {
2010
2010
  console.warn("\\u26A0 Admin user creation skipped:", (err as Error).message);
2011
- }`}function Mi(e,t){let o=t.has("Tenant"),n=t.has("User"),r=t.has("Project"),s=Li(e,n),i=o?` let tenants: Array<{ id: string; name: string }> = [];
2011
+ }`}function Yi(e,t){let o=t.has("Tenant"),n=t.has("User"),r=t.has("Project"),s=$i(e,n),i=o?` let tenants: Array<{ id: string; name: string }> = [];
2012
2012
  try {
2013
2013
  tenants = await Promise.all([
2014
2014
  prisma.tenant.create({
@@ -2077,12 +2077,12 @@ main()
2077
2077
  .finally(async () => {
2078
2078
  await prisma.$disconnect();
2079
2079
  });
2080
- `}function Di(e){if(ue.existsSync(e))try{let t=ue.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};ue.writeFileSync(e,JSON.stringify(i,null,2)+`
2081
- `)}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 jo(e,t){let o=Oi(e);if(o)try{let n=xe.join(o.packageDir,"prisma","schema.prisma"),r=Ui(n),s=Mi(t,r),i=xe.dirname(o.seedPath);ue.existsSync(i)||ue.mkdirSync(i,{recursive:!0}),ue.writeFileSync(o.seedPath,s),Di(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 me from"fs";import Ne 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:""}],ol=jt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Vo(e){return jt.find(t=>t.id===e)}var Fi="@nebutra/sms",ji={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 sn(e,t){me.mkdirSync(Ne.dirname(e),{recursive:!0}),me.writeFileSync(e,t)}function Vi(e,t){let o=Ne.join(e,".env.example");me.existsSync(o)?me.appendFileSync(o,`
2082
- `+t):me.writeFileSync(o,t)}function Ki(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2080
+ `}function qi(e){if(ue.existsSync(e))try{let t=ue.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};ue.writeFileSync(e,JSON.stringify(i,null,2)+`
2081
+ `)}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 Yo(e,t){let o=Ki(e);if(o)try{let n=xe.join(o.packageDir,"prisma","schema.prisma"),r=Bi(n),s=Yi(t,r),i=xe.dirname(o.seedPath);ue.existsSync(i)||ue.mkdirSync(i,{recursive:!0}),ue.writeFileSync(o.seedPath,s),qi(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 me from"fs";import Te from"path";var Kt=[{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:""}],fl=Kt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function qo(e){return Kt.find(t=>t.id===e)}var Gi="@nebutra/sms",Hi={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 cn(e,t){me.mkdirSync(Te.dirname(e),{recursive:!0}),me.writeFileSync(e,t)}function Wi(e,t){let o=Te.join(e,".env.example");me.existsSync(o)?me.appendFileSync(o,`
2082
+ `+t):me.writeFileSync(o,t)}function Xi(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2083
2083
  `);return`${t}
2084
2084
  ${o}
2085
- `}var Bi=`/**
2085
+ `}var zi=`/**
2086
2086
  * Inputs for the \`sendSms\` wrapper. Keep this surface portable across
2087
2087
  * providers \u2014 provider-specific options belong in the wrapper itself.
2088
2088
  */
@@ -2102,7 +2102,7 @@ export interface SendSmsResult {
2102
2102
  provider: string;
2103
2103
  raw?: unknown;
2104
2104
  }
2105
- `;function $i(){return`import twilio from "twilio";
2105
+ `;function Ji(){return`import twilio from "twilio";
2106
2106
  import type { SendSmsInput, SendSmsResult } from "./types";
2107
2107
 
2108
2108
  let client: ReturnType<typeof twilio> | null = null;
@@ -2137,7 +2137,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2137
2137
  }
2138
2138
 
2139
2139
  export type { SendSmsInput, SendSmsResult } from "./types";
2140
- `}function Yi(){return`import messagebird from "messagebird";
2140
+ `}function Qi(){return`import messagebird from "messagebird";
2141
2141
  import type { SendSmsInput, SendSmsResult } from "./types";
2142
2142
 
2143
2143
  let client: ReturnType<typeof messagebird> | null = null;
@@ -2175,7 +2175,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2175
2175
  }
2176
2176
 
2177
2177
  export type { SendSmsInput, SendSmsResult } from "./types";
2178
- `}function qi(){return`import plivo from "plivo";
2178
+ `}function Zi(){return`import plivo from "plivo";
2179
2179
  import type { SendSmsInput, SendSmsResult } from "./types";
2180
2180
 
2181
2181
  let client: InstanceType<typeof plivo.Client> | null = null;
@@ -2214,7 +2214,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2214
2214
  }
2215
2215
 
2216
2216
  export type { SendSmsInput, SendSmsResult } from "./types";
2217
- `}function Gi(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2217
+ `}function ea(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2218
2218
  import * as $OpenApi from "@alicloud/openapi-client";
2219
2219
  import type { SendSmsInput, SendSmsResult } from "./types";
2220
2220
 
@@ -2263,7 +2263,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2263
2263
  }
2264
2264
 
2265
2265
  export type { SendSmsInput, SendSmsResult } from "./types";
2266
- `}function Hi(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2266
+ `}function ta(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2267
2267
  import type { SendSmsInput, SendSmsResult } from "./types";
2268
2268
 
2269
2269
  const SmsClient = tencentcloud.sms.v20210111.Client;
@@ -2328,7 +2328,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2328
2328
  }
2329
2329
 
2330
2330
  export type { SendSmsInput, SendSmsResult } from "./types";
2331
- `}function Wi(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2331
+ `}function na(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2332
2332
  import Yunpian from "yunpian-nodejs-sdk";
2333
2333
  import type { SendSmsInput, SendSmsResult } from "./types";
2334
2334
 
@@ -2380,13 +2380,13 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2380
2380
  }
2381
2381
 
2382
2382
  export type { SendSmsInput, SendSmsResult } from "./types";
2383
- `}function Xi(e){switch(e){case"twilio":return $i();case"messagebird":return Yi();case"plivo":return qi();case"aliyun-sms":return Gi();case"tencent-sms":return Hi();case"yunpian":return Wi();case"none":return`export {};
2384
- `}}function zi(e){let t={};for(let n of e.pkgs??[]){let r=ji[n];r&&(t[n]=r)}let o={name:Fi,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)+`
2385
- `}async function Ko(e,t,o="global"){if(t==="none")return;let n=Vo(t);if(!n)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${jt.map(i=>i.id).join(", ")}`);let r=Ne.join(e,"packages","sms");if(!me.existsSync(r))return;let s=Ne.join(r,"src");me.existsSync(s)&&me.rmSync(s,{recursive:!0,force:!0});try{sn(Ne.join(r,"package.json"),zi(n)),sn(Ne.join(s,"types.ts"),Bi),sn(Ne.join(s,"index.ts"),Xi(n.id)),Vi(e,Ki(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 Oe from"fs";import Te from"path";var St=[{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 an(e){let t=e==="supabase"?"supabase-storage":e;return St.some(o=>o.id===t)?t:void 0}function Bo(e){let t=an(e);return t?St.find(o=>o.id===t):void 0}var pl=St.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Ue="@nebutra/storage";function cn(e,t){Oe.mkdirSync(Te.dirname(e),{recursive:!0}),Oe.writeFileSync(e,t)}function Ji(e,t){let o=Te.join(e,".env.example");Oe.existsSync(o)?Oe.appendFileSync(o,`
2386
- `+t):Oe.writeFileSync(o,t)}function Qi(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2383
+ `}function oa(e){switch(e){case"twilio":return Ji();case"messagebird":return Qi();case"plivo":return Zi();case"aliyun-sms":return ea();case"tencent-sms":return ta();case"yunpian":return na();case"none":return`export {};
2384
+ `}}function ra(e){let t={};for(let n of e.pkgs??[]){let r=Hi[n];r&&(t[n]=r)}let o={name:Gi,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)+`
2385
+ `}async function Go(e,t,o="global"){if(t==="none")return;let n=qo(t);if(!n)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${Kt.map(i=>i.id).join(", ")}`);let r=Te.join(e,"packages","sms");if(!me.existsSync(r))return;let s=Te.join(r,"src");me.existsSync(s)&&me.rmSync(s,{recursive:!0,force:!0});try{cn(Te.join(r,"package.json"),ra(n)),cn(Te.join(s,"types.ts"),zi),cn(Te.join(s,"index.ts"),oa(n.id)),Wi(e,Xi(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 Oe from"fs";import Ne from"path";var ht=[{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 pn(e){let t=e==="supabase"?"supabase-storage":e;return ht.some(o=>o.id===t)?t:void 0}function Ho(e){let t=pn(e);return t?ht.find(o=>o.id===t):void 0}var _l=ht.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Ue="@nebutra/storage";function ln(e,t){Oe.mkdirSync(Ne.dirname(e),{recursive:!0}),Oe.writeFileSync(e,t)}function sa(e,t){let o=Ne.join(e,".env.example");Oe.existsSync(o)?Oe.appendFileSync(o,`
2386
+ `+t):Oe.writeFileSync(o,t)}function ia(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2387
2387
  `);return`${t}
2388
2388
  ${o}
2389
- `}var Zi=`/**
2389
+ `}var aa=`/**
2390
2390
  * Inputs for the \`uploadFile\` wrapper. Keep this surface portable across
2391
2391
  * providers \u2014 provider-specific options belong in the wrapper itself.
2392
2392
  */
@@ -2412,7 +2412,7 @@ export interface SignedUrlOptions {
2412
2412
  operation?: "get" | "put";
2413
2413
  contentType?: string;
2414
2414
  }
2415
- `;function ea(){return`/**
2415
+ `;function ca(){return`/**
2416
2416
  * @${Ue.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
2417
2417
  *
2418
2418
  * Docs: https://developers.cloudflare.com/r2/api/s3/api/
@@ -2476,7 +2476,7 @@ export async function getSignedUrl(
2476
2476
  }
2477
2477
 
2478
2478
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2479
- `}function ta(){return`/**
2479
+ `}function pa(){return`/**
2480
2480
  * @${Ue.slice(1)} \u2014 AWS S3 wrapper.
2481
2481
  *
2482
2482
  * Docs: https://docs.aws.amazon.com/s3/
@@ -2541,7 +2541,7 @@ export async function getSignedUrl(
2541
2541
  }
2542
2542
 
2543
2543
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2544
- `}function na(){return`/**
2544
+ `}function la(){return`/**
2545
2545
  * @${Ue.slice(1)} \u2014 Supabase Storage wrapper.
2546
2546
  *
2547
2547
  * Docs: https://supabase.com/docs/guides/storage
@@ -2604,7 +2604,7 @@ export async function getSignedUrl(
2604
2604
  }
2605
2605
 
2606
2606
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2607
- `}function oa(){return`/**
2607
+ `}function da(){return`/**
2608
2608
  * @${Ue.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2609
2609
  *
2610
2610
  * Docs: https://help.aliyun.com/product/31815.html
@@ -2651,7 +2651,7 @@ export async function getSignedUrl(
2651
2651
  }
2652
2652
 
2653
2653
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2654
- `}function ra(){return`/**
2654
+ `}function ua(){return`/**
2655
2655
  * @${Ue.slice(1)} \u2014 \u817E\u8BAF\u4E91 COS wrapper via cos-nodejs-sdk-v5.
2656
2656
  *
2657
2657
  * Docs: https://cloud.tencent.com/document/product/436
@@ -2706,7 +2706,7 @@ export async function getSignedUrl(
2706
2706
  }
2707
2707
 
2708
2708
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2709
- `}function sa(){return`/**
2709
+ `}function ma(){return`/**
2710
2710
  * @${Ue.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2711
2711
  *
2712
2712
  * Docs: https://developer.qiniu.com/kodo
@@ -2774,9 +2774,9 @@ export async function getSignedUrl(
2774
2774
  }
2775
2775
 
2776
2776
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2777
- `}function ia(e){switch(e){case"r2":return ea();case"s3":return ta();case"supabase-storage":return na();case"aliyun-oss":return oa();case"tencent-cos":return ra();case"qiniu":return sa();case"none":return`export {};
2778
- `}}function aa(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:Ue,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)+`
2779
- `}async function $o(e,t,o){if(t==="none")return;let n=Bo(t);if(!n)throw new Error(`Unknown storage provider "${t}". Valid ids: ${St.map(i=>i.id).join(", ")}`);let r=Te.join(e,"packages","storage"),s=Te.join(r,"src");Oe.existsSync(s)&&Oe.rmSync(s,{recursive:!0,force:!0}),cn(Te.join(r,"package.json"),aa(n)),cn(Te.join(s,"types.ts"),Zi),cn(Te.join(s,"index.ts"),ia(n.id)),Ji(e,Qi(n))}function ge(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 Yo(e,t){let o=t==="cn";return{cronJobs:ge(e.cronJobs,!0),auditLog:ge(e.auditLog,!0),apiKeys:ge(e.apiKeys,!0),webhooks:ge(e.webhooks,!0),commandPalette:ge(e.commandPalette,!0),cookieConsent:ge(e.cookieConsent,!0),legalPages:ge(e.legalPages,!0),chinaCompliance:ge(e.chinaCompliance,o)}}var Vt=[{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 qo(e){return Vt.find(t=>t.id===e)}var yl=Vt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Go(e,t,o="global"){let n=qo(t);if(!n)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Vt.map(r=>r.id).join(", ")}`);if(n.id==="none"){G(e,"webhooks");return}n.envVars.length>0&&Q(e,{category:"Webhooks",name:n.name,envVars:n.envVars,docs:n.docs}),Z(e,"WEBHOOKS_PROVIDER",n.id)}import Le from"fs";import ht from"path";function ca(e){return`import Link from "next/link";
2777
+ `}function ga(e){switch(e){case"r2":return ca();case"s3":return pa();case"supabase-storage":return la();case"aliyun-oss":return da();case"tencent-cos":return ua();case"qiniu":return ma();case"none":return`export {};
2778
+ `}}function fa(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:Ue,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)+`
2779
+ `}async function Wo(e,t,o){if(t==="none")return;let n=Ho(t);if(!n)throw new Error(`Unknown storage provider "${t}". Valid ids: ${ht.map(i=>i.id).join(", ")}`);let r=Ne.join(e,"packages","storage"),s=Ne.join(r,"src");Oe.existsSync(s)&&Oe.rmSync(s,{recursive:!0,force:!0}),ln(Ne.join(r,"package.json"),fa(n)),ln(Ne.join(s,"types.ts"),aa),ln(Ne.join(s,"index.ts"),ga(n.id)),sa(e,ia(n))}function ge(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 Xo(e,t){let o=t==="cn";return{cronJobs:ge(e.cronJobs,!0),auditLog:ge(e.auditLog,!0),apiKeys:ge(e.apiKeys,!0),webhooks:ge(e.webhooks,!0),commandPalette:ge(e.commandPalette,!0),cookieConsent:ge(e.cookieConsent,!0),legalPages:ge(e.legalPages,!0),chinaCompliance:ge(e.chinaCompliance,o)}}var Bt=[{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 zo(e){return Bt.find(t=>t.id===e)}var Rl=Bt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Jo(e,t,o="global"){let n=zo(t);if(!n)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Bt.map(r=>r.id).join(", ")}`);if(n.id==="none"){H(e,"webhooks");return}n.envVars.length>0&&Q(e,{category:"Webhooks",name:n.name,envVars:n.envVars,docs:n.docs}),Z(e,"WEBHOOKS_PROVIDER",n.id)}import Le from"fs";import Et from"path";function ya(e){return`import Link from "next/link";
2780
2780
 
2781
2781
  export default function WelcomePage() {
2782
2782
  const projectName = ${JSON.stringify(e)};
@@ -2885,21 +2885,21 @@ function Step({
2885
2885
  </li>
2886
2886
  );
2887
2887
  }
2888
- `}function pa(e={}){return`
2888
+ `}function Sa(e={}){return`
2889
2889
  ## What you can do next
2890
2890
 
2891
2891
  ${[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(`
2892
2892
  `)}
2893
- `}function la(e=[]){return e.length===0?"":`
2893
+ `}function ha(e=[]){return e.length===0?"":`
2894
2894
  ## Production readiness holds
2895
2895
 
2896
2896
  Do not enable these in production until you replace stubs, add provider credentials, and verify the integration contract:
2897
2897
 
2898
- ${e.map(o=>{let n=Je(o.status);return`- ${o.flag}=${o.provider} ${n} \u2014 ${ce(o.status)}`}).join(`
2898
+ ${e.map(o=>{let n=Qe(o.status);return`- ${o.flag}=${o.provider} ${n} \u2014 ${ce(o.status)}`}).join(`
2899
2899
  `)}
2900
2900
 
2901
2901
  Review the package readiness matrix before handoff: [docs/package-status.md](docs/package-status.md)
2902
- `}function da(e,t,o=[],n={}){return`# Next steps \u2014 ${e}
2902
+ `}function Ea(e,t,o=[],n={}){return`# Next steps \u2014 ${e}
2903
2903
 
2904
2904
  Region: ${t}
2905
2905
 
@@ -2925,17 +2925,17 @@ Your AI-native SaaS scaffold is ready. Complete these four steps to go from temp
2925
2925
  \`\`\`
2926
2926
 
2927
2927
  After setup, delete the welcome route at \`apps/web/src/app/[locale]/welcome/\`.
2928
- ${pa(n)}${la(o)}
2928
+ ${Sa(n)}${ha(o)}
2929
2929
 
2930
2930
  ## Resources
2931
2931
 
2932
2932
  - [Documentation](/docs)
2933
2933
  - [GitHub](https://github.com/nebutra/nebutra-sailor)
2934
2934
  - [Get free license (Individual/OPC)](https://nebutra.com/get-license)
2935
- `}async function Ho(e,t){let{projectName:o,region:n,previewSelections:r=[],waveFeatures:s={}}=t;try{let i=ht.join(e,".sailor");Le.existsSync(i)||Le.mkdirSync(i,{recursive:!0}),Le.writeFileSync(ht.join(i,"next-steps.md"),da(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=ht.join(e,"apps","web");if(!Le.existsSync(i))return;let c=ht.join(i,"src","app","[locale]","welcome");Le.existsSync(c)||Le.mkdirSync(c,{recursive:!0}),Le.writeFileSync(ht.join(c,"page.tsx"),ca(o))}catch(i){let c=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write welcome page: ${c}`)}}var Wo="create-sailor";function p(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2936
- `)}function ga(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function Xo(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 zo(e,t,o){let n=e?.trim().toLowerCase()??Dn(t),r=Tt(n);if(!r){let i=Jt.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 Jo(e){return"prisma"}function Qo(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function Zo(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 er(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==="none"?"none":"clerk"}var fa=new Set(["gateway","direct","custom","none"]);function ar(e){if(!e)return!1;let t=e.trim().toLowerCase();return fa.has(t)}function tr(e){if(!e)return["openai"];if(ar(e))return[];let t=e.split(",").map(o=>o.trim().toLowerCase());return t.includes("none")?[]:t}function ya(e,t){let o=e??t;return an(o)??o}var nr={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function or(e,t){if(!e)return"fumadocs";let o=e.toLowerCase();if(o==="fumadocs"||o==="none")return o;if(o in nr){let n=nr[o];return t?p(!0,{event:"notice",kind:"docs-fallback",requested:o,effective:"fumadocs"}):process.stdout.write(C.yellow(`\u26A0 ${n} support is coming in v1.2. Falling back to fumadocs.
2935
+ `}async function Qo(e,t){let{projectName:o,region:n,previewSelections:r=[],waveFeatures:s={}}=t;try{let i=Et.join(e,".sailor");Le.existsSync(i)||Le.mkdirSync(i,{recursive:!0}),Le.writeFileSync(Et.join(i,"next-steps.md"),Ea(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=Et.join(e,"apps","web");if(!Le.existsSync(i))return;let c=Et.join(i,"src","app","[locale]","welcome");Le.existsSync(c)||Le.mkdirSync(c,{recursive:!0}),Le.writeFileSync(Et.join(c,"page.tsx"),ya(o))}catch(i){let c=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write welcome page: ${c}`)}}var Zo="create-sailor";function p(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2936
+ `)}function ba(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function er(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 tr(e,t,o){let n=e?.trim().toLowerCase()??jn(t),r=Ot(n);if(!r){let i=Zt.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 nr(e){return e==="drizzle"?"drizzle":"prisma"}function or(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function rr(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 sr(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==="none"?"none":"clerk"}var Pa=new Set(["gateway","direct","custom","none"]);function ur(e){if(!e)return!1;let t=e.trim().toLowerCase();return Pa.has(t)}function ir(e){if(!e)return["openai"];if(ur(e))return[];let t=e.split(",").map(o=>o.trim().toLowerCase());return t.includes("none")?[]:t}function Ca(e,t){let o=e??t;return pn(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(C.yellow(`\u26A0 ${n} support is coming in v1.2. Falling back to fumadocs.
2937
2937
  `)+C.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
2938
- `)),"fumadocs"}return"fumadocs"}function rr(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 sr(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function Sa(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"}}function ir(e){return e==="cn"?"wechat":"stripe"}async function ha(){let e=new ua;e.name(Wo).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 (only \u2014 the scaffold uses Prisma. Drizzle support is on the roadmap)").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 | 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("--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("--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&&(fn(),process.exit(0));let n=!!t.json,r=!!t.dryRun,s=!!t.yes,i=s||!process.stdin.isTTY;if(n||un(),p(n,{event:"start",version:ae}),!t.pm)try{Et("pnpm --version",{stdio:"ignore"})}catch{n||process.stderr.write(`
2938
+ `)),"fumadocs"}return"fumadocs"}function pr(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 lr(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function Ia(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"}}function dr(e){return e==="cn"?"wechat":"stripe"}async function Aa(){let e=new va;e.name(Zo).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 | 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("--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("--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&&(Sn(),process.exit(0));let n=!!t.json,r=!!t.dryRun,s=!!t.yes,i=s||!process.stdin.isTTY;if(n||gn(),p(n,{event:"start",version:ae}),!t.pm)try{vt("pnpm --version",{stdio:"ignore"})}catch{n||process.stderr.write(`
2939
2939
  ${C.red("\u2718")} ${C.bold("pnpm is required")} but was not found on PATH.
2940
2940
 
2941
2941
  The scaffold uses pnpm workspaces + Turborepo. Install pnpm first:
@@ -2945,22 +2945,22 @@ Then retry: ${C.cyan("pnpm dlx create-sailor@latest")}
2945
2945
  (or pass ${C.dim("--pm=npm")} if you know workspace:* won't resolve in your setup)
2946
2946
 
2947
2947
  `),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 x.group({name:()=>x.text({message:"Where should we create your project?",placeholder:"./my-saas-app",defaultValue:"./my-saas-app",validate:E=>{if(E.length===0)return"Please enter a path."}})},{onCancel:()=>{process.stdout.write(C.red(`\u2718 Cancelled
2948
- `)),process.exit(130)}});a=String(g.name)}let l=vt.basename(vt.resolve(a)),m=t.pm??ga(),S=!!t.region,N=!!t.auth,T=!!t.payment,D=!!t.ai,ie=!!t.email,b=!!t.storage,u=!!t.monitoring,U=!!t.analytics,_t=!!t.sms,pn=t.i18n!==void 0,h,rt,W,bt="local",st,$,F,X=Cn(t.socialLogin),it,Kt,ye,Me,ne,Y,Pt;if(i){h=sr(t.region),rt=Jo(t.orm);{let oe=Xo(t.db),y=zo(t.dbHost,h,oe);W=y.engine,bt=y.hostId}let g=T?t.payment:ir(h);st=Qo(g),$=Zo(g),F=er(t.auth);let E="gateway";if(D){let oe=t.ai?.trim().toLowerCase()??"";ar(oe)?E=oe:E="direct"}let O=Gt({mode:E,providerIds:D?tr(t.ai):void 0});it=O.mode,Kt=O.routing,ye=O.providerIds,ne=rr(t.deploy),Y=or(t.docs,n),Pt=pn?!!t.i18n:!0}else{let g={};S||(g.region=()=>x.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"})),N||(g.auth=()=>x.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:"none",label:"None"}],initialValue:"clerk"})),D||(g.aiMode=()=>x.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:v})=>{if(v.aiMode!=="direct")return Promise.resolve([]);let K=qt.map($t=>({value:$t.id,label:`[${$t.category}] ${$t.name}`}));return x.multiselect({message:"Select direct AI provider adapters (expert path)",options:K,initialValues:["openai"],required:!1})},g.customAiName=({results:v})=>v.aiMode==="custom"?x.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),g.customAiBaseUrl=({results:v})=>v.aiMode==="custom"?x.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:K=>{if(K.length===0)return"Base URL is required."}}):Promise.resolve(void 0),g.customAiApiKeyEnv=({results:v})=>v.aiMode==="custom"?x.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0));let E=Object.keys(g).length>0?await x.group(g,{onCancel:()=>{process.stdout.write(C.red(`\u2718 Cancelled
2949
- `)),process.exit(130)}}):{};h=sr(S?t.region:E.region),rt=Jo(t.orm);{let v=Xo(t.db),K=zo(t.dbHost,h,v);W=K.engine,bt=K.hostId}let O=T?t.payment:ir(h);st=Qo(O),$=Zo(O),F=er(N?t.auth:E.auth);let oe=E.aiMode==="custom"?{name:E.customAiName??"custom",baseURL:E.customAiBaseUrl??"",apiKeyEnvName:E.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,y=Gt({mode:D?t.ai?.trim().toLowerCase()==="none"?"none":"direct":E.aiMode??"gateway",providerIds:D?tr(t.ai):E.aiProviders,customEndpoint:oe});it=y.mode,Kt=y.routing,ye=y.providerIds,y.customEndpoint&&(Me={name:y.customEndpoint.name,baseURL:y.customEndpoint.baseURL,apiKeyEnvName:y.customEndpoint.apiKeyEnvName}),ne=rr(t.deploy),Y=or(t.docs,n),Pt=pn?!!t.i18n:!0}let w=Sa(h),De=ie?t.email:w.email,Fe=ya(b?t.storage:void 0,w.storage),je=u?t.monitoring:w.monitoring,Ve=U?t.analytics:w.analytics,Ke=_t?t.sms:w.sms,Be=t.queue??w.queue,$e=t.search??w.search,at=t.cache??w.cache,Ye=t.notifications??w.notifications,qe=t.webhooks??w.webhooks,ct=t.cms??w.cms,Ge=t.featureFlags??w.featureFlags,He=t.captcha??w.captcha,Ct=t.mcp??w.mcp,pt=t.metering??w.metering,We=t.billingMode??w.billingMode,Xe=t.idp??w.idp,I=Yo({cronJobs:t.cronJobs,auditLog:t.auditLog,apiKeys:t.apiKeys,commandPalette:t.commandPalette,cookieConsent:t.cookieConsent,legalPages:t.legalPages,chinaCompliance:t.chinaCompliance},h),ze=mn([{flag:"queue",provider:Be},{flag:"search",provider:$e},{flag:"notifications",provider:Ye},{flag:"webhooks",provider:qe},{flag:"feature-flags",provider:Ge},{flag:"captcha",provider:He}]);function Bt(){for(let g of ze)if(n)p(!0,{event:"warn",step:g.flag,provider:g.provider,packageStatus:g.status,message:ce(g.status)});else{let E=Je(g.status);process.stdout.write(C.yellow(`\u26A0 ${g.flag}=${g.provider} ${E} \u2014 ${ce(g.status)}
2950
- `))}}let Se={region:h,orm:rt,database:W,payment:st,aiMode:it,aiRouting:Kt,aiProviders:ye,customAiEndpoint:Me,deployTarget:ne,docs:Y,i18n:Pt,email:De,storage:Fe,monitoring:je,analytics:Ve,sms:Ke,queue:Be,search:$e,cache:at,notifications:Ye,webhooks:qe,cms:ct,featureFlags:Ge,captcha:He,mcp:Ct,metering:pt,billingMode:We,idp:Xe,cronJobs:I.cronJobs,auditLog:I.auditLog,apiKeys:I.apiKeys,commandPalette:I.commandPalette,cookieConsent:I.cookieConsent,legalPages:I.legalPages,chinaCompliance:I.chinaCompliance},It=[["Project name",l],["Region",h],["Auth",F],["Social login",X.length>0?X.map(g=>lt.find(E=>E.id===g)?.name??g).join(", "):"none"],["ORM",rt],["Database",W],["Payment",$],["AI topology",`${it}${ye.length>0?` (${ye.join(", ")} seed)`:""}${Me?" + custom endpoint":""}`],["Email",De],["Storage",Fe],["Monitoring",je],["Analytics",Ve],["SMS",Ke],["Deploy Target",ne],["Docs Framework",Y]];n?It.forEach(([g,E],O)=>{p(!0,{event:"step",step:g,value:E,index:O+1,total:It.length})}):It.forEach(([g,E],O)=>{Sn({index:O+1,total:It.length,label:g,value:E})});let cr={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""},ln=Date.now();if(r){let g=ye.length,E=[`clone template \u2192 ${a}`,"write nebutra.config.json",`prune template (orm=${rt}, i18n=${Pt})`,`region \u2192 ${h}`,`auth \u2192 ${F==="none"?"skip (remove packages/auth)":`configure ${F}`}`,...X.length>0?[`social-login \u2192 generate ${X.length} callback route${X.length===1?"":"s"} + SocialLoginButtons.tsx (${X.join(", ")})`]:[],`db \u2192 ${W==="none"?"skip (remove packages/db)":`configure Prisma for ${W}`}`,`payment \u2192 ${$==="none"?"skip (remove packages/billing)":`configure ${$}`}`,...Y!=="none"?[`docs \u2192 scaffold apps/docs (${Y==="fumadocs"?"fumadocs":`${Y} \u2192 fumadocs fallback`})`]:[],...g>0||Me?[`ai-providers \u2192 generate ${it} registry seed + env (${g}${Me?" + custom":""} provider${g===1&&!Me?"":"s"})`]:[],...De!=="none"?[`email \u2192 configure ${De}`]:[],...Fe!=="none"?[`storage \u2192 configure ${Fe}`]:[],...je!=="none"?[`monitoring \u2192 configure ${je}`]:[],...Ve!=="none"?[`analytics \u2192 configure ${Ve}`]:[],...Ke!=="none"?[`sms \u2192 configure ${Ke}`]:[],...Be!=="none"?[`queue \u2192 configure ${Be}`]:[],...$e!=="none"?[`search \u2192 configure ${$e}`]:[],...at!=="none"?[`cache \u2192 configure ${at}`]:[],...Ye!=="none"?[`notifications \u2192 configure ${Ye}`]:[],...qe!=="none"?[`webhooks \u2192 configure ${qe}`]:[],...ct!=="none"?[`cms \u2192 configure ${ct}`]:[],...Ge!=="none"?[`feature-flags \u2192 configure ${Ge}`]:[],...He!=="none"?[`captcha \u2192 configure ${He}`]:[],`mcp \u2192 ${Ct==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${pt==="off"?"disabled":pt==="auto"?st!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...We!=="usage"?[`billing-mode \u2192 ${We}`]:[],...Xe!=="clerk"?[`idp \u2192 ${Xe}`]:[],`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 ${h} 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)",...ne!=="none"?[`deploy \u2192 inject ${ne} config`]:[],"inject .env.local",t.install===!1?"skip install":`run ${m} install`,t.git===!1?"skip git init":"run git init"];if(n){for(let O of E)p(!0,{event:"plan",action:O});Bt(),p(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2948
+ `)),process.exit(130)}});a=String(g.name)}let l=_t.basename(_t.resolve(a)),m=t.pm??ba(),S=!!t.region,T=!!t.auth,N=!!t.payment,D=!!t.ai,ie=!!t.email,b=!!t.storage,u=!!t.monitoring,U=!!t.analytics,bt=!!t.sms,dn=t.i18n!==void 0,h,Me,$,Pt="local",it,Y,F,X=An(t.socialLogin),at,$t,ye,De,ne,q,Ct;if(i){h=lr(t.region),Me=nr(t.orm);{let oe=er(t.db),y=tr(t.dbHost,h,oe);$=y.engine,Pt=y.hostId}let g=N?t.payment:dr(h);it=or(g),Y=rr(g),F=sr(t.auth);let E="gateway";if(D){let oe=t.ai?.trim().toLowerCase()??"";ur(oe)?E=oe:E="direct"}let O=Wt({mode:E,providerIds:D?ir(t.ai):void 0});at=O.mode,$t=O.routing,ye=O.providerIds,ne=pr(t.deploy),q=cr(t.docs,n),Ct=dn?!!t.i18n:!0}else{let g={};S||(g.region=()=>x.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"})),T||(g.auth=()=>x.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:"none",label:"None"}],initialValue:"clerk"})),D||(g.aiMode=()=>x.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:v})=>{if(v.aiMode!=="direct")return Promise.resolve([]);let K=Ht.map(qt=>({value:qt.id,label:`[${qt.category}] ${qt.name}`}));return x.multiselect({message:"Select direct AI provider adapters (expert path)",options:K,initialValues:["openai"],required:!1})},g.customAiName=({results:v})=>v.aiMode==="custom"?x.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),g.customAiBaseUrl=({results:v})=>v.aiMode==="custom"?x.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:K=>{if(K.length===0)return"Base URL is required."}}):Promise.resolve(void 0),g.customAiApiKeyEnv=({results:v})=>v.aiMode==="custom"?x.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0));let E=Object.keys(g).length>0?await x.group(g,{onCancel:()=>{process.stdout.write(C.red(`\u2718 Cancelled
2949
+ `)),process.exit(130)}}):{};h=lr(S?t.region:E.region),Me=nr(t.orm);{let v=er(t.db),K=tr(t.dbHost,h,v);$=K.engine,Pt=K.hostId}let O=N?t.payment:dr(h);it=or(O),Y=rr(O),F=sr(T?t.auth:E.auth);let oe=E.aiMode==="custom"?{name:E.customAiName??"custom",baseURL:E.customAiBaseUrl??"",apiKeyEnvName:E.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,y=Wt({mode:D?t.ai?.trim().toLowerCase()==="none"?"none":"direct":E.aiMode??"gateway",providerIds:D?ir(t.ai):E.aiProviders,customEndpoint:oe});at=y.mode,$t=y.routing,ye=y.providerIds,y.customEndpoint&&(De={name:y.customEndpoint.name,baseURL:y.customEndpoint.baseURL,apiKeyEnvName:y.customEndpoint.apiKeyEnvName}),ne=pr(t.deploy),q=cr(t.docs,n),Ct=dn?!!t.i18n:!0}let w=Ia(h),Fe=ie?t.email:w.email,je=Ca(b?t.storage:void 0,w.storage),Ve=u?t.monitoring:w.monitoring,Ke=U?t.analytics:w.analytics,Be=bt?t.sms:w.sms,$e=t.queue??w.queue,Ye=t.search??w.search,ct=t.cache??w.cache,qe=t.notifications??w.notifications,Ge=t.webhooks??w.webhooks,pt=t.cms??w.cms,He=t.featureFlags??w.featureFlags,We=t.captcha??w.captcha,It=t.mcp??w.mcp,lt=t.metering??w.metering,Xe=t.billingMode??w.billingMode,ze=t.idp??w.idp,I=Xo({cronJobs:t.cronJobs,auditLog:t.auditLog,apiKeys:t.apiKeys,commandPalette:t.commandPalette,cookieConsent:t.cookieConsent,legalPages:t.legalPages,chinaCompliance:t.chinaCompliance},h),Je=fn([{flag:"queue",provider:$e},{flag:"search",provider:Ye},{flag:"notifications",provider:qe},{flag:"webhooks",provider:Ge},{flag:"feature-flags",provider:He},{flag:"captcha",provider:We}]);function Yt(){for(let g of Je)if(n)p(!0,{event:"warn",step:g.flag,provider:g.provider,packageStatus:g.status,message:ce(g.status)});else{let E=Qe(g.status);process.stdout.write(C.yellow(`\u26A0 ${g.flag}=${g.provider} ${E} \u2014 ${ce(g.status)}
2950
+ `))}}let Se={region:h,orm:Me,database:$,payment:it,aiMode:at,aiRouting:$t,aiProviders:ye,customAiEndpoint:De,deployTarget:ne,docs:q,i18n:Ct,email:Fe,storage:je,monitoring:Ve,analytics:Ke,sms:Be,queue:$e,search:Ye,cache:ct,notifications:qe,webhooks:Ge,cms:pt,featureFlags:He,captcha:We,mcp:It,metering:lt,billingMode:Xe,idp:ze,cronJobs:I.cronJobs,auditLog:I.auditLog,apiKeys:I.apiKeys,commandPalette:I.commandPalette,cookieConsent:I.cookieConsent,legalPages:I.legalPages,chinaCompliance:I.chinaCompliance},At=[["Project name",l],["Region",h],["Auth",F],["Social login",X.length>0?X.map(g=>dt.find(E=>E.id===g)?.name??g).join(", "):"none"],["ORM",Me],["Database",$],["Payment",Y],["AI topology",`${at}${ye.length>0?` (${ye.join(", ")} seed)`:""}${De?" + custom endpoint":""}`],["Email",Fe],["Storage",je],["Monitoring",Ve],["Analytics",Ke],["SMS",Be],["Deploy Target",ne],["Docs Framework",q]];n?At.forEach(([g,E],O)=>{p(!0,{event:"step",step:g,value:E,index:O+1,total:At.length})}):At.forEach(([g,E],O)=>{En({index:O+1,total:At.length,label:g,value:E})});let mr={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""},un=Date.now();if(r){let g=ye.length,E=[`clone template \u2192 ${a}`,"write nebutra.config.json",`prune template (orm=${Me}, i18n=${Ct})`,`region \u2192 ${h}`,`auth \u2192 ${F==="none"?"skip (remove packages/auth)":`configure ${F}`}`,...X.length>0?[`social-login \u2192 generate ${X.length} callback route${X.length===1?"":"s"} + SocialLoginButtons.tsx (${X.join(", ")})`]:[],`db \u2192 ${$==="none"?"skip (remove packages/db)":`configure Prisma for ${$}`}`,`payment \u2192 ${Y==="none"?"skip (remove packages/billing)":`configure ${Y}`}`,...q!=="none"?[`docs \u2192 scaffold apps/docs (${q==="fumadocs"?"fumadocs":`${q} \u2192 fumadocs fallback`})`]:[],...g>0||De?[`ai-providers \u2192 generate ${at} registry seed + env (${g}${De?" + custom":""} provider${g===1&&!De?"":"s"})`]:[],...Fe!=="none"?[`email \u2192 configure ${Fe}`]:[],...je!=="none"?[`storage \u2192 configure ${je}`]:[],...Ve!=="none"?[`monitoring \u2192 configure ${Ve}`]:[],...Ke!=="none"?[`analytics \u2192 configure ${Ke}`]:[],...Be!=="none"?[`sms \u2192 configure ${Be}`]:[],...$e!=="none"?[`queue \u2192 configure ${$e}`]:[],...Ye!=="none"?[`search \u2192 configure ${Ye}`]:[],...ct!=="none"?[`cache \u2192 configure ${ct}`]:[],...qe!=="none"?[`notifications \u2192 configure ${qe}`]:[],...Ge!=="none"?[`webhooks \u2192 configure ${Ge}`]:[],...pt!=="none"?[`cms \u2192 configure ${pt}`]:[],...He!=="none"?[`feature-flags \u2192 configure ${He}`]:[],...We!=="none"?[`captcha \u2192 configure ${We}`]:[],`mcp \u2192 ${It==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${lt==="off"?"disabled":lt==="auto"?it!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...Xe!=="usage"?[`billing-mode \u2192 ${Xe}`]:[],...ze!=="clerk"?[`idp \u2192 ${ze}`]:[],`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 ${h} 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)",...ne!=="none"?[`deploy \u2192 inject ${ne} config`]:[],"inject .env.local",t.install===!1?"skip install":`run ${m} install`,t.git===!1?"skip git init":"run git init"];if(n){for(let O of E)p(!0,{event:"plan",action:O});Yt(),p(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2951
2951
  `+C.bold(`Dry run \u2014 planned actions:
2952
2952
  `));for(let O of E)process.stdout.write(` \u2022 ${O}
2953
- `);ze.length>0&&(process.stdout.write(`
2953
+ `);Je.length>0&&(process.stdout.write(`
2954
2954
  `+C.bold(C.yellow(`Preview-status providers selected:
2955
- `))),Bt()),process.stdout.write(C.dim(`
2955
+ `))),Yt()),process.stdout.write(C.dim(`
2956
2956
  No files were written.
2957
- `))}process.exit(0)}let pr=async()=>{process.stdout.write(`
2957
+ `))}process.exit(0)}let gr=async()=>{process.stdout.write(`
2958
2958
  `+C.red(`\u2718 Cancelled
2959
2959
  `)),fe.existsSync(a)&&await x.confirm({message:`Cleanup partial install at ${a}?`,initialValue:!0})===!0&&(fe.rmSync(a,{recursive:!0,force:!0}),process.stdout.write(C.dim(` \u2713 Removed ${a}
2960
- `))),process.exit(130)};process.on("SIGINT",pr);try{p(n,{event:"step",step:"clone",status:"start"}),await lo(a),p(n,{event:"step",step:"clone",status:"ok"}),p(n,{event:"step",step:"package",status:"start"}),await vo(a,l),p(n,{event:"step",step:"package",status:"ok"}),p(n,{event:"step",step:"config",status:"start"}),await Mn(a,Se),p(n,{event:"step",step:"config",status:"ok"}),p(n,{event:"step",step:"prune",status:"start"}),await ko(a,Se),p(n,{event:"step",step:"prune",status:"ok"});let g=vt.join(a,"packages/platform/db/prisma/schema.prisma");if(fe.existsSync(g)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let y=fe.readFileSync(g,"utf-8"),v=rn(y,{auth:F,payment:$,"billing-mode":We,idp:Xe,template:"saas"});fe.writeFileSync(g,v),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(y){let v=y instanceof Error?y.message:String(y);p(n,{event:"step",step:"schema-prune",status:"error",error:v})}}else p(n,{event:"step",step:"schema-prune",status:"skip"});if(p(n,{event:"step",step:"auth",choice:F,status:"start"}),await bn(a,F),p(n,{event:"step",step:"auth",choice:F,status:"ok"}),X.length>0?(p(n,{event:"step",step:"social-login",providers:X,status:"start"}),await An(a,X,F),p(n,{event:"step",step:"social-login",providers:X,status:"ok"})):p(n,{event:"step",step:"social-login",status:"skip"}),p(n,{event:"step",step:"db",choice:W,status:"start"}),await Vn(a,W,l),W!=="none"){let y=Tt(bt);y&&(await Kn(a,y,l),p(n,{event:"step",step:"db-host",choice:bt,status:"ok"}))}if(p(n,{event:"step",step:"db",choice:W,status:"ok"}),p(n,{event:"step",step:"payment",choice:$,status:"start"}),await bo(a,$),p(n,{event:"step",step:"payment",choice:$,status:"ok"}),await zn(a,De,h),n&&p(!0,{event:"step",step:"email",choice:De,status:"ok"}),await $o(a,Fe,h),n&&p(!0,{event:"step",step:"storage",choice:Fe,status:"ok"}),await So(a,je,h),n&&p(!0,{event:"step",step:"monitoring",choice:je,status:"ok"}),await vn(a,Ve,h),n&&p(!0,{event:"step",step:"analytics",choice:Ve,status:"ok"}),await Ko(a,Ke,h),n&&p(!0,{event:"step",step:"sms",choice:Ke,status:"ok"}),await Uo(a,Be,h),n&&p(!0,{event:"step",step:"queue",choice:Be,status:"ok"}),await Fo(a,$e,h),n&&p(!0,{event:"step",step:"search",choice:$e,status:"ok"}),await xn(a,at,h),n&&p(!0,{event:"step",step:"cache",choice:at,status:"ok"}),await Eo(a,Ye,h),n&&p(!0,{event:"step",step:"notifications",choice:Ye,status:"ok"}),await Go(a,qe,h),n&&p(!0,{event:"step",step:"webhooks",choice:qe,status:"ok"}),await Un(a,ct,h),n&&p(!0,{event:"step",step:"cms",choice:ct,status:"ok"}),await oo(a,Ge,h),n&&p(!0,{event:"step",step:"feature-flags",choice:Ge,status:"ok"}),await Tn(a,He,h),n&&p(!0,{event:"step",step:"captcha",choice:He,status:"ok"}),await uo(a,Ct),n&&p(!0,{event:"step",step:"mcp",mode:Ct,status:"ok"}),await go(a,pt,st),n&&p(!0,{event:"step",step:"metering",mode:pt,status:"ok"}),p(n,{event:"step",step:"prune-wave-features",status:"start"}),xo(a,I),p(n,{event:"step",step:"prune-wave-features",status:"ok",toggles:I}),Se.orm==="prisma"&&Se.database!=="none"){let y=vt.join(a,"packages/platform/db/prisma/schema.prisma");if(fe.existsSync(y)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let v=fe.readFileSync(y,"utf8"),K=rn(v,{auth:F,payment:$,"billing-mode":We,idp:Xe,template:"saas"});fe.writeFileSync(y,K),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(v){let K=v instanceof Error?v.message:String(v);p(n,{event:"step",step:"schema-prune",status:"error",error:K})}}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:We,status:"ok"}),p(n,{event:"step",step:"idp",choice:Xe,status:"ok"}),await Ln(a,h),n&&p(!0,{event:"step",step:"compliance",region:h,status:"ok"}),await to(a),await jo(a,F),await Ho(a,{projectName:l,region:h,previewSelections:ze,waveFeatures:I}),Se.aiMode!=="none"){p(n,{event:"step",step:"ai-providers",status:"start"});let y={providerIds:Se.aiProviders,customEndpoint:Se.customAiEndpoint},v=vt.join(a,"packages/ai/ai-providers/templates");await wo(a,y,v),p(n,{event:"step",step:"ai-providers",status:"ok"})}else p(n,{event:"step",step:"ai-providers",status:"skip"});if(p(n,{event:"step",step:"docs",status:"start"}),Y!=="none"?(await Gn(a,{framework:Y,projectName:l}),p(n,{event:"step",step:"docs",framework:"fumadocs",requested:Y,status:"ok"})):p(n,{event:"step",step:"docs",status:"skip"}),p(n,{event:"step",step:"deploy-target",status:"start"}),ne!=="none"&&await $n(a,ne),p(n,{event:"step",step:"deploy-target",status:"ok"}),p(n,{event:"step",step:"env",status:"start"}),await Qn(a,cr),p(n,{event:"step",step:"env",status:"ok"}),t.install!==!1){let y=m==="bun"?"bun install":`${m} install`;n?p(!0,{event:"step",step:"install",pm:m,status:"start"}):process.stdout.write(C.dim(` Installing dependencies with ${m}\u2026
2961
- `));try{Et(y,{cwd:a,stdio:n?"ignore":"inherit"}),p(n,{event:"step",step:"install",status:"ok"})}catch(v){let K=v instanceof Error?v.message:String(v);n?p(!0,{event:"step",step:"install",status:"error",error:K}):process.stdout.write(C.yellow(` \u26A0 install failed \u2014 run '${y}' manually.
2962
- `))}}else p(n,{event:"step",step:"install",status:"skip"});if(t.git!==!1){n&&p(!0,{event:"step",step:"git-init",status:"start"});try{Et("git init -q",{cwd:a,stdio:"ignore"}),Et("git add -A",{cwd:a,stdio:"ignore"}),Et('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(y){let v=y instanceof Error?y.message:String(y);n?p(!0,{event:"step",step:"git-init",status:"error",error:v}):process.stdout.write(C.yellow(` \u26A0 git init skipped \u2014 not fatal.
2963
- `))}}else p(n,{event:"step",step:"git-init",status:"skip"});let oe=Math.max(1,Math.round((Date.now()-ln)/1e3));_n({template_version:ae,package_manager:m,region:h,auth:F,payment:$,ai_providers:ye,deploy_target:ne,duration_ms:Date.now()-ln}),ze.length>0&&Bt(),n?p(!0,{event:"done",status:"ok",elapsedSec:oe,targetDir:a,previewSelections:ze,waveFeatures:I}):gn({elapsedSec:oe,targetDir:a,skippedInstall:t.install===!1,previewSelections:ze,waveFeatures:I});try{ma({pkg:{name:Wo,version:ae},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}process.exit(0)}catch(g){let E=g instanceof Error?g.message:String(g);n?p(!0,{event:"error",message:E}):process.stdout.write(C.red(`
2960
+ `))),process.exit(130)};process.on("SIGINT",gr);try{p(n,{event:"step",step:"clone",status:"start"}),await mo(a),p(n,{event:"step",step:"clone",status:"ok"}),p(n,{event:"step",step:"package",status:"start"}),await bo(a,l),p(n,{event:"step",step:"package",status:"ok"}),p(n,{event:"step",step:"config",status:"start"}),await Fn(a,Se),p(n,{event:"step",step:"config",status:"ok"}),p(n,{event:"step",step:"prune",status:"start"}),await Uo(a,Se),p(n,{event:"step",step:"prune",status:"ok"});let g=_t.join(a,"packages/platform/db/prisma/schema.prisma");if(fe.existsSync(g)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let y=fe.readFileSync(g,"utf-8"),v=an(y,{auth:F,payment:Y,"billing-mode":Xe,idp:ze,template:"saas"});fe.writeFileSync(g,v),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(y){let v=y instanceof Error?y.message:String(y);p(n,{event:"step",step:"schema-prune",status:"error",error:v})}}else p(n,{event:"step",step:"schema-prune",status:"skip"});if(p(n,{event:"step",step:"auth",choice:F,status:"start"}),await Cn(a,F),p(n,{event:"step",step:"auth",choice:F,status:"ok"}),X.length>0?(p(n,{event:"step",step:"social-login",providers:X,status:"start"}),await Rn(a,X,F),p(n,{event:"step",step:"social-login",providers:X,status:"ok"})):p(n,{event:"step",step:"social-login",status:"skip"}),p(n,{event:"step",step:"db",choice:$,status:"start"}),await Bn(a,$,l),$!=="none"){let y=Ot(Pt);y&&(await $n(a,y,l),p(n,{event:"step",step:"db-host",choice:Pt,status:"ok"}))}if(p(n,{event:"step",step:"db",choice:$,status:"ok"}),Me==="drizzle"){p(n,{event:"step",step:"orm",choice:"drizzle",status:"start"});let y=await Io(a,"drizzle",$);p(n,{event:"step",step:"orm",choice:"drizzle",status:y.applied?"ok":"skip",...y.reason?{reason:y.reason}:{}})}if(p(n,{event:"step",step:"payment",choice:Y,status:"start"}),await wo(a,Y),p(n,{event:"step",step:"payment",choice:Y,status:"ok"}),await Qn(a,Fe,h),n&&p(!0,{event:"step",step:"email",choice:Fe,status:"ok"}),await Wo(a,je,h),n&&p(!0,{event:"step",step:"storage",choice:je,status:"ok"}),await Eo(a,Ve,h),n&&p(!0,{event:"step",step:"monitoring",choice:Ve,status:"ok"}),await bn(a,Ke,h),n&&p(!0,{event:"step",step:"analytics",choice:Ke,status:"ok"}),await Go(a,Be,h),n&&p(!0,{event:"step",step:"sms",choice:Be,status:"ok"}),await jo(a,$e,h),n&&p(!0,{event:"step",step:"queue",choice:$e,status:"ok"}),await $o(a,Ye,h),n&&p(!0,{event:"step",step:"search",choice:Ye,status:"ok"}),await Nn(a,ct,h),n&&p(!0,{event:"step",step:"cache",choice:ct,status:"ok"}),await _o(a,qe,h),n&&p(!0,{event:"step",step:"notifications",choice:qe,status:"ok"}),await Jo(a,Ge,h),n&&p(!0,{event:"step",step:"webhooks",choice:Ge,status:"ok"}),await Mn(a,pt,h),n&&p(!0,{event:"step",step:"cms",choice:pt,status:"ok"}),await so(a,He,h),n&&p(!0,{event:"step",step:"feature-flags",choice:He,status:"ok"}),await Un(a,We,h),n&&p(!0,{event:"step",step:"captcha",choice:We,status:"ok"}),await go(a,It),n&&p(!0,{event:"step",step:"mcp",mode:It,status:"ok"}),await yo(a,lt,it),n&&p(!0,{event:"step",step:"metering",mode:lt,status:"ok"}),p(n,{event:"step",step:"prune-wave-features",status:"start"}),Lo(a,I),p(n,{event:"step",step:"prune-wave-features",status:"ok",toggles:I}),Se.orm==="prisma"&&Se.database!=="none"){let y=_t.join(a,"packages/platform/db/prisma/schema.prisma");if(fe.existsSync(y)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let v=fe.readFileSync(y,"utf8"),K=an(v,{auth:F,payment:Y,"billing-mode":Xe,idp:ze,template:"saas"});fe.writeFileSync(y,K),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(v){let K=v instanceof Error?v.message:String(v);p(n,{event:"step",step:"schema-prune",status:"error",error:K})}}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:Xe,status:"ok"}),p(n,{event:"step",step:"idp",choice:ze,status:"ok"}),await Dn(a,h),n&&p(!0,{event:"step",step:"compliance",region:h,status:"ok"}),await oo(a),await Yo(a,F),await Qo(a,{projectName:l,region:h,previewSelections:Je,waveFeatures:I}),Se.aiMode!=="none"){p(n,{event:"step",step:"ai-providers",status:"start"});let y={providerIds:Se.aiProviders,customEndpoint:Se.customAiEndpoint},v=_t.join(a,"packages/ai/ai-providers/templates");await No(a,y,v),p(n,{event:"step",step:"ai-providers",status:"ok"})}else p(n,{event:"step",step:"ai-providers",status:"skip"});if(p(n,{event:"step",step:"docs",status:"start"}),q!=="none"?(await Wn(a,{framework:q,projectName:l}),p(n,{event:"step",step:"docs",framework:"fumadocs",requested:q,status:"ok"})):p(n,{event:"step",step:"docs",status:"skip"}),p(n,{event:"step",step:"deploy-target",status:"start"}),ne!=="none"&&await qn(a,ne),p(n,{event:"step",step:"deploy-target",status:"ok"}),p(n,{event:"step",step:"env",status:"start"}),await eo(a,mr),p(n,{event:"step",step:"env",status:"ok"}),t.install!==!1){let y=m==="bun"?"bun install":`${m} install`;n?p(!0,{event:"step",step:"install",pm:m,status:"start"}):process.stdout.write(C.dim(` Installing dependencies with ${m}\u2026
2961
+ `));try{vt(y,{cwd:a,stdio:n?"ignore":"inherit"}),p(n,{event:"step",step:"install",status:"ok"})}catch(v){let K=v instanceof Error?v.message:String(v);n?p(!0,{event:"step",step:"install",status:"error",error:K}):process.stdout.write(C.yellow(` \u26A0 install failed \u2014 run '${y}' manually.
2962
+ `))}}else p(n,{event:"step",step:"install",status:"skip"});if(t.git!==!1){n&&p(!0,{event:"step",step:"git-init",status:"start"});try{vt("git init -q",{cwd:a,stdio:"ignore"}),vt("git add -A",{cwd:a,stdio:"ignore"}),vt('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(y){let v=y instanceof Error?y.message:String(y);n?p(!0,{event:"step",step:"git-init",status:"error",error:v}):process.stdout.write(C.yellow(` \u26A0 git init skipped \u2014 not fatal.
2963
+ `))}}else p(n,{event:"step",step:"git-init",status:"skip"});let oe=Math.max(1,Math.round((Date.now()-un)/1e3));Pn({template_version:ae,package_manager:m,region:h,auth:F,payment:Y,ai_providers:ye,deploy_target:ne,duration_ms:Date.now()-un}),Je.length>0&&Yt(),n?p(!0,{event:"done",status:"ok",elapsedSec:oe,targetDir:a,previewSelections:Je,waveFeatures:I}):yn({elapsedSec:oe,targetDir:a,skippedInstall:t.install===!1,previewSelections:Je,waveFeatures:I});try{_a({pkg:{name:Zo,version:ae},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}process.exit(0)}catch(g){let E=g instanceof Error?g.message:String(g);n?p(!0,{event:"error",message:E}):process.stdout.write(C.red(`
2964
2964
  \u2718 Failed: ${E}
2965
- `)),process.exit(1)}}ha().catch(e=>{process.stderr.write(String(e)+`
2965
+ `)),process.exit(1)}}Aa().catch(e=>{process.stderr.write(String(e)+`
2966
2966
  `),process.exit(1)});