create-sailor 1.3.1 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/aws-kms-BRGZLC2X.js +1 -0
  2. package/dist/chunk-2VIWVVHK.js +1 -0
  3. package/dist/chunk-4F23MJOI.js +1 -0
  4. package/dist/chunk-6EI2BXXZ.js +1 -0
  5. package/dist/chunk-7DCGNQSQ.js +5 -0
  6. package/dist/chunk-7HOF72FC.js +1 -0
  7. package/dist/chunk-7VJYOZUP.js +2 -0
  8. package/dist/chunk-7Z3O7WJM.js +49 -0
  9. package/dist/chunk-B35GFLVZ.js +5 -0
  10. package/dist/chunk-BAI5W3AB.js +1 -0
  11. package/dist/chunk-DGJUBN33.js +1 -0
  12. package/dist/chunk-DIXI4M5O.js +1 -0
  13. package/dist/chunk-EA5HU2X4.js +9 -0
  14. package/dist/chunk-EXLRPVEX.js +1 -0
  15. package/dist/chunk-FGJ5K4WM.js +1 -0
  16. package/dist/chunk-HC3S5NWW.js +1 -0
  17. package/dist/chunk-KIX47M2V.js +40 -0
  18. package/dist/chunk-LOPYJ44X.js +31 -0
  19. package/dist/chunk-O3WYNHSC.js +20 -0
  20. package/dist/chunk-OJM5Y4UT.js +1 -0
  21. package/dist/chunk-PXU2OOBT.js +1 -0
  22. package/dist/chunk-QEIMNOY2.js +1 -0
  23. package/dist/chunk-QMKVUKS6.js +1 -0
  24. package/dist/chunk-RR5R4AKJ.js +1 -0
  25. package/dist/chunk-XSSPJU77.js +1 -0
  26. package/dist/chunk-YW4FFW47.js +1 -0
  27. package/dist/chunk-ZEEOYOWD.js +1 -0
  28. package/dist/credits-L2HL2UEU.js +1787 -0
  29. package/dist/dist-XS6SQF6X.js +5 -0
  30. package/dist/dist-Z6UUHTH2.js +8 -0
  31. package/dist/dist-es-M3FWVZJF.js +1 -0
  32. package/dist/dist-es-NDZJSZR3.js +2 -0
  33. package/dist/dist-es-NVFYVK4E.js +1 -0
  34. package/dist/dist-es-OUTR3NFA.js +5 -0
  35. package/dist/dist-es-UGE2JJUB.js +1 -0
  36. package/dist/dist-es-VHZAJVLW.js +1 -0
  37. package/dist/dist-es-WTYBIVJ2.js +2 -0
  38. package/dist/event-streams-WTP73PI5.js +1 -0
  39. package/dist/getMachineId-bsd-DVN24SFH.js +1 -0
  40. package/dist/getMachineId-darwin-LMU6AYNV.js +2 -0
  41. package/dist/getMachineId-linux-BHWLMOUW.js +1 -0
  42. package/dist/getMachineId-unsupported-G5LY7Y3J.js +1 -0
  43. package/dist/getMachineId-win-CWK62SDK.js +1 -0
  44. package/dist/index.js +189 -178
  45. package/dist/loadSso-O5OGD76B.js +1 -0
  46. package/dist/local-V5XPOCXA.js +1 -0
  47. package/dist/multipart-parser-73SROTP5.js +2 -0
  48. package/dist/query_compiler_fast_bg.postgresql-7BFUBDOL.js +2 -0
  49. package/dist/query_compiler_fast_bg.postgresql.wasm-base64-I4FAC6EL.js +1 -0
  50. package/dist/signin-DZIPNQBV.js +1 -0
  51. package/dist/src-BFSJ5KFS.js +3 -0
  52. package/dist/src-ERQKJBBE.js +1 -0
  53. package/dist/sso-oidc-SYBBWZG3.js +1 -0
  54. package/dist/sts-DREA5KZD.js +6 -0
  55. package/package.json +14 -11
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import{execSync as At}from"child_process";import go from"fs";import Yt from"path";import*as P from"@clack/prompts";import{Command as pi}from"commander";import x from"picocolors";import li from"update-notifier";import ko from"cfonts";import Oo from"picocolors";import $t from"fs";import Rt from"path";import{fileURLToPath as xo}from"url";function To(){try{let t=Rt.dirname(xo(import.meta.url));for(let o=0;o<4;o++){let n=Rt.join(t,"package.json");if($t.existsSync(n)){let r=$t.readFileSync(n,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=Rt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var se=To();function qt(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${se}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
3
- `));return}ko.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(Oo.dim(` AI-Native SaaS Template \xB7 v${se} \xB7 nebutra.com
2
+ import"./chunk-DGJUBN33.js";import{execSync as Ot}from"child_process";import ue from"fs";import dt from"path";import*as C from"@clack/prompts";import{Command as Li}from"commander";import R from"picocolors";import Mi from"update-notifier";import $o from"cfonts";import qo from"picocolors";import Zt from"fs";import Lt from"path";import{fileURLToPath as Bo}from"url";function Yo(){try{let t=Lt.dirname(Bo(import.meta.url));for(let o=0;o<4;o++){let n=Lt.join(t,"package.json");if(Zt.existsSync(n)){let r=Zt.readFileSync(n,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=Lt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var ne=Yo();function en(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${ne}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
3
+ `));return}$o.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(qo.dim(` AI-Native SaaS Template \xB7 v${ne} \xB7 nebutra.com
4
4
 
5
- `))}import j from"picocolors";function Uo(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Gt(e){let t=Uo(),o=t?"\u2693":"-",n=t?"\u25B8":"->",r=t?"\u2605":"*",s=t?"\u{1F4E7}":"*",c=["",` ${t?j.bold(`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`):`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`}`,"",` ${t?j.bold("Next:"):"Next:"}`,` ${n} cd ${e.targetDir}`];e.skippedInstall&&c.push(` ${n} pnpm install (if --no-install was set)`),c.push(` ${n} pnpm dev ${t?j.dim("\u2192 http://localhost:3000"):"-> http://localhost:3000"}`,"",` ${t?j.bold("Customize:"):"Customize:"}`,` ${n} pnpm sailor brand init ${t?j.dim("\u2192 your colors, logo, domain"):"-> your colors, logo, domain"}`,` ${n} pnpm sailor preset apply ${t?j.dim("\u2192 toggle features"):"-> toggle features"}`,` ${n} pnpm sailor add <feat> ${t?j.dim("\u2192 add queue/search/cache/..."):"-> add queue/search/cache/..."}`,"",` ${t?j.bold("Add more features later:"):"Add more features later:"}`,` ${n} sailor add payment --provider=wechat`,` ${n} sailor add email --provider=postmark`,` ${n} sailor add storage --provider=supabase`,` ${t?j.dim("(more providers: `sailor add --list`)"):"(more providers: `sailor add --list`)"}`,"",` ${t?j.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 h from"picocolors";var Go={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 Ho(e){return e?Go[e]??"stable":"stable"}function St(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function qe(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 tn(e){let t=[];for(let{flag:o,provider:n}of e){if(!n||n==="none")continue;let r=Ho(n);r!=="stable"&&t.push({flag:o,provider:n,status:r})}return t}function Wo(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function nn(e){let t=Wo(),o=t?"\u2693":"-",n=t?"\u25B8":"->",r=t?"\u2605":"*",s=t?"\u{1F4E7}":"*",c=["",` ${t?h.bold(`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`):`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`}`,"",` ${t?h.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?h.dim("\u2192 add provider keys before booting apps"):"-> add provider keys before booting apps"}`,` ${n} pnpm db:migrate ${t?h.dim("\u2192 sync Prisma schema"):"-> sync Prisma schema"}`,` ${n} pnpm db:seed ${t?h.dim("\u2192 load example tenants and records"):"-> load example tenants and records"}`,` ${n} pnpm dev ${t?h.dim("\u2192 http://localhost:3000"):"-> http://localhost:3000"}`,"",` ${t?h.bold("Customize:"):"Customize:"}`,` ${n} pnpm brand:init ${t?h.dim("\u2192 create brand.config.ts"):"-> create brand.config.ts"}`,` ${n} pnpm brand:apply ${t?h.dim("\u2192 propagate brand changes"):"-> propagate brand changes"}`,` ${n} pnpm preset:env ${t?h.dim("\u2192 review preset env requirements"):"-> review preset env requirements"}`,"",` ${t?h.bold("Useful scripts:"):"Useful scripts:"}`,` ${n} pnpm infra:up ${t?h.dim("\u2192 start local PostgreSQL/Redis/ClickHouse"):"-> start local PostgreSQL/Redis/ClickHouse"}`,` ${n} pnpm generate:api-types ${t?h.dim("\u2192 refresh shared API client types"):"-> refresh shared API client types"}`,` ${n} pnpm lint ${t?h.dim("\u2192 quick repo sanity check"):"-> quick repo sanity check"}`);let i=e.previewSelections??[];if(i.length>0){let d=t?h.bold(h.yellow("\u26A0 Preview features selected:")):"!! Preview features selected:";c.push("",` ${d}`);for(let u of i){let S=St(u.status),U=` ${n} ${u.flag} (${u.provider}) ${S}`;c.push(t?h.yellow(U):U)}c.push("",` ${t?h.dim(qe("foundation")):qe("foundation")}`,` ${t?h.dim("You may need to contribute the provider integration yourself."):"You may need to contribute the provider integration yourself."}`,` ${t?h.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"}`)}c.push("",` ${t?h.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 Lo=`Usage: create-sailor [name] [options]
7
+ `)}var Xo=`Usage: create-sailor [name] [options]
8
8
 
9
9
  Arguments:
10
10
  name project directory (default: ./my-saas-app)
@@ -28,14 +28,21 @@ Feature flags (region-based smart defaults):
28
28
  --monitoring <id> sentry | datadog | aliyun-arms | tingyun | none
29
29
  --analytics <id> posthog | plausible | umami | baidu | sensors | none
30
30
  --sms <id> twilio | aliyun-sms | tencent-sms | yunpian | none
31
- --queue <id> qstash | bullmq | upstash | sqs | none
32
- --search <id> meilisearch | typesense | algolia | pgvector | none
31
+ --queue <id> qstash | bullmq | upstash | sqs | none [Foundation]
32
+ --search <id> meilisearch | typesense | algolia | pgvector | none [Foundation]
33
33
  --cache <id> upstash-redis | vercel-kv | redis | dragonfly | none
34
- --notifications <id> novu | knock | custom | none
35
- --webhooks <id> svix | custom | none
34
+ --notifications <id> novu | knock | custom | none [Foundation]
35
+ --webhooks <id> svix | custom | none [Foundation]
36
36
  --cms <id> sanity | contentful | strapi | none
37
- --feature-flags <id> vercel-flags | growthbook | configcat | none
38
- --captcha <id> turnstile | hcaptcha | aliyun-slide | none
37
+ --feature-flags <id> vercel-flags | growthbook | configcat | none [WIP]
38
+ --captcha <id> turnstile | hcaptcha | aliyun-slide | none [WIP]
39
+ --billing-mode <mode> usage | seat | credits (default: usage)
40
+ --idp <id> clerk | oauth-server (default: clerk)
41
+
42
+ Preview statuses:
43
+ [Foundation] \u2014 types + factory complete; adapters need external credentials & may not work out-of-the-box
44
+ [WIP] \u2014 actively being built; do not use in production
45
+ See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md
39
46
 
40
47
  Sailor features:
41
48
  --mcp <mode> on | off (default: on \u2014 Agent-friendly MCP server)
@@ -59,9 +66,9 @@ Examples:
59
66
  $ npm create sailor@latest my-app --region=cn --auth=clerk
60
67
  $ npm create sailor@latest my-app --region=hybrid --ai=openai,deepseek
61
68
  $ npm create sailor@latest --dry-run --region=cn
62
- `;function Ht(){process.stdout.write(Lo)}import dt from"picocolors";function Wt(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Mo(e){let t=Wt()?"\u25B8":"->",o=`[${e.index}/${e.total}]`,n=e.label.padEnd(18," ");return Wt()?`${dt.dim(o)} ${dt.bold(n)} ${dt.dim(t)} ${dt.cyan(e.value)}`:`${o} ${n} ${t} ${e.value}`}function Xt(e){process.stdout.write(Mo(e)+`
63
- `)}var ut=[{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:[]}],Ri=ut.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});import Te from"fs";import A from"path";var zt=[{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:""}],Ni=zt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Qt(e){return zt.find(t=>t.id===e)}function Do(e){Te.mkdirSync(e,{recursive:!0})}function F(e,t){Do(A.dirname(e)),Te.writeFileSync(e,t)}function ie(e,t){let o=A.join(e,".env.example");Te.existsSync(o)?Te.appendFileSync(o,`
64
- `+t):Te.writeFileSync(o,t)}function jo(e){let t=`"use client";
69
+ `;function on(){process.stdout.write(Xo)}import Et from"picocolors";function rn(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function zo(e){let t=rn()?"\u25B8":"->",o=`[${e.index}/${e.total}]`,n=e.label.padEnd(18," ");return rn()?`${Et.dim(o)} ${Et.bold(n)} ${Et.dim(t)} ${Et.cyan(e.value)}`:`${o} ${n} ${t} ${e.value}`}function sn(e){process.stdout.write(zo(e)+`
70
+ `)}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:[]}],ta=ht.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var Qo="https://analytics.nebutra.com";function Jo(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function an(e,t={}){Jo(t)||(async()=>{try{let o=await import("./dist-XS6SQF6X.js");if(typeof o.createAnalyticsClient!="function")return;let n=o.createAnalyticsClient({posthog:{apiKey:process.env.NEBUTRA_POSTHOG_KEY??"",host:process.env.NEBUTRA_POSTHOG_HOST??Qo},onError:()=>{}});if(typeof n?.track!="function")return;let r=n.track("scaffold.completed",e);r&&typeof r.then=="function"&&await r.catch(()=>{})}catch{}})()}import Ge from"fs";import T from"path";var cn=[{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:""}],ra=cn.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function pn(e){return cn.find(t=>t.id===e)}function Zo(e){Ge.mkdirSync(e,{recursive:!0})}function q(e,t){Zo(T.dirname(e)),Ge.writeFileSync(e,t)}function me(e,t){let o=T.join(e,".env.example");Ge.existsSync(o)?Ge.appendFileSync(o,`
71
+ `+t):Ge.writeFileSync(o,t)}function er(e){let t=`"use client";
65
72
  /**
66
73
  * PostHog browser SDK \u2014 lazy-initialized on first access.
67
74
  */
@@ -144,11 +151,11 @@ export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
144
151
 
145
152
  return <>{children}</>;
146
153
  }
147
- `;F(A.join(e,"src","lib","analytics","posthog.client.ts"),t),F(A.join(e,"src","lib","analytics","posthog.server.ts"),o),F(A.join(e,"src","components","analytics","AnalyticsProvider.tsx"),n)}function Fo(){return`# PostHog \u2014 product analytics
154
+ `;q(T.join(e,"src","lib","analytics","posthog.client.ts"),t),q(T.join(e,"src","lib","analytics","posthog.server.ts"),o),q(T.join(e,"src","components","analytics","AnalyticsProvider.tsx"),n)}function tr(){return`# PostHog \u2014 product analytics
148
155
  POSTHOG_KEY=
149
156
  NEXT_PUBLIC_POSTHOG_KEY=
150
157
  NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
151
- `}function Vo(e){F(A.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
158
+ `}function nr(e){q(T.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
152
159
  /**
153
160
  * Plausible script tag \u2014 lightweight, privacy-friendly analytics.
154
161
  */
@@ -168,10 +175,10 @@ export function PlausibleScript() {
168
175
  />
169
176
  );
170
177
  }
171
- `)}function Ko(){return`# Plausible \u2014 privacy-friendly analytics
178
+ `)}function or(){return`# Plausible \u2014 privacy-friendly analytics
172
179
  NEXT_PUBLIC_PLAUSIBLE_DOMAIN=
173
180
  NEXT_PUBLIC_PLAUSIBLE_SRC=https://plausible.io/js/script.js
174
- `}function Yo(e){F(A.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
181
+ `}function rr(e){q(T.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
175
182
  /**
176
183
  * Umami analytics \u2014 self-hosted OR umami.is cloud.
177
184
  */
@@ -191,10 +198,10 @@ export function UmamiScript() {
191
198
  />
192
199
  );
193
200
  }
194
- `)}function Bo(){return`# Umami \u2014 self-hostable analytics
201
+ `)}function sr(){return`# Umami \u2014 self-hostable analytics
195
202
  NEXT_PUBLIC_UMAMI_WEBSITE_ID=
196
203
  NEXT_PUBLIC_UMAMI_SRC=https://cloud.umami.is/script.js
197
- `}function $o(e){let t=`"use client";
204
+ `}function ir(e){let t=`"use client";
198
205
  import mixpanel from "mixpanel-browser";
199
206
 
200
207
  let initialized = false;
@@ -233,10 +240,10 @@ export function trackServer(
233
240
  if (!c) return;
234
241
  c.track(event, { distinct_id: distinctId, ...properties });
235
242
  }
236
- `;F(A.join(e,"src","lib","analytics","mixpanel.client.ts"),t),F(A.join(e,"src","lib","analytics","mixpanel.server.ts"),o)}function qo(){return`# Mixpanel \u2014 product analytics
243
+ `;q(T.join(e,"src","lib","analytics","mixpanel.client.ts"),t),q(T.join(e,"src","lib","analytics","mixpanel.server.ts"),o)}function ar(){return`# Mixpanel \u2014 product analytics
237
244
  MIXPANEL_TOKEN=
238
245
  NEXT_PUBLIC_MIXPANEL_TOKEN=
239
- `}function Go(e){F(A.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
246
+ `}function cr(e){q(T.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
240
247
  /**
241
248
  * \u767E\u5EA6\u7EDF\u8BA1 Baidu Tongji \u2014 hm.js \u57CB\u70B9\u811A\u672C.
242
249
  */
@@ -262,9 +269,9 @@ var _hmt = _hmt || [];
262
269
  />
263
270
  );
264
271
  }
265
- `)}function Ho(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
272
+ `)}function pr(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
266
273
  NEXT_PUBLIC_BAIDU_STATS_ID=
267
- `}function Wo(e){F(A.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
274
+ `}function lr(e){q(T.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
268
275
  /**
269
276
  * \u795E\u7B56\u5206\u6790 (Sensors Analytics) \u2014 sa-sdk-javascript \u5C01\u88C5.
270
277
  */
@@ -292,10 +299,10 @@ export function initSensors(): void {
292
299
  }
293
300
 
294
301
  export { sensors };
295
- `)}function Xo(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
302
+ `)}function dr(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
296
303
  NEXT_PUBLIC_SENSORS_SERVER_URL=
297
304
  NEXT_PUBLIC_SENSORS_APP_JS_URL=
298
- `}function zo(e){F(A.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
305
+ `}function ur(e){q(T.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
299
306
  /**
300
307
  * GrowingIO CDP \u2014 inline snippet installer.
301
308
  */
@@ -320,21 +327,21 @@ gdp("send");
320
327
  />
321
328
  );
322
329
  }
323
- `)}function Qo(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
330
+ `)}function mr(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
324
331
  NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID=
325
- `}async function Jt(e,t,o="global"){let n=Qt(t);if(!n||n.id==="none")return;let r=A.join(e,"apps","web");if(!Te.existsSync(r))return;let s=n.id;try{switch(s){case"posthog":jo(r),ie(e,Fo());return;case"plausible":Vo(r),ie(e,Ko());return;case"umami":Yo(r),ie(e,Bo());return;case"mixpanel":$o(r),ie(e,qo());return;case"baidu":Go(r),ie(e,Ho());return;case"sensors":Wo(r),ie(e,Xo());return;case"growingio":zo(r),ie(e,Qo());return;default:return}}catch(a){throw console.error(`Failed to apply analytics selection "${t}":`,a),new Error(`Analytics scaffold for "${t}" failed \u2014 see stderr for details.`)}}import w from"fs";import ae from"path";function wt(e){w.existsSync(e)&&w.rmSync(e,{recursive:!0,force:!0})}function Zt(e,t){let o=ae.join(e,".env.example");w.existsSync(o)?w.appendFileSync(o,`
326
- `+t):w.writeFileSync(o,t)}function en(e,t){if(!w.existsSync(e))return;let o=w.readFileSync(e,"utf8"),n=o.replace(/export type AuthProviderId\s*=\s*"[^"]+"\s*\|\s*"[^"]+";/,`export type AuthProviderId = "${t}";`);n!==o&&w.writeFileSync(e,n)}function Jo(e,t){let o=ae.join(e,"README.md");if(!w.existsSync(o)){w.writeFileSync(o,t);return}w.appendFileSync(o,`
327
- `+t)}async function tn(e,t){let o=ae.join(e,"packages","auth");if(!w.existsSync(o))return;if(t==="none"){wt(o),Jo(e,`
332
+ `}async function ln(e,t,o="global"){let n=pn(t);if(!n||n.id==="none")return;let r=T.join(e,"apps","web");if(!Ge.existsSync(r))return;let s=n.id;try{switch(s){case"posthog":er(r),me(e,tr());return;case"plausible":nr(r),me(e,or());return;case"umami":rr(r),me(e,sr());return;case"mixpanel":ir(r),me(e,ar());return;case"baidu":cr(r),me(e,pr());return;case"sensors":lr(r),me(e,dr());return;case"growingio":ur(r),me(e,mr());return;default:return}}catch(a){throw console.error(`Failed to apply analytics selection "${t}":`,a),new Error(`Analytics scaffold for "${t}" failed \u2014 see stderr for details.`)}}import M from"fs";import ge from"path";function Mt(e){M.existsSync(e)&&M.rmSync(e,{recursive:!0,force:!0})}function dn(e,t){let o=ge.join(e,".env.example");M.existsSync(o)?M.appendFileSync(o,`
333
+ `+t):M.writeFileSync(o,t)}function un(e,t){if(!M.existsSync(e))return;let o=M.readFileSync(e,"utf8"),n=o.replace(/export type AuthProviderId\s*=\s*"[^"]+"\s*\|\s*"[^"]+";/,`export type AuthProviderId = "${t}";`);n!==o&&M.writeFileSync(e,n)}function gr(e,t){let o=ge.join(e,"README.md");if(!M.existsSync(o)){M.writeFileSync(o,t);return}M.appendFileSync(o,`
334
+ `+t)}async function mn(e,t){let o=ge.join(e,"packages","auth");if(!M.existsSync(o))return;if(t==="none"){Mt(o),gr(e,`
328
335
  ## Auth
329
336
 
330
337
  Auth was skipped at scaffold time (\`--auth=none\`). Add your preferred auth provider manually (e.g. Clerk, Better Auth, NextAuth).
331
- `);return}let n=ae.join(o,"src","providers"),r=ae.join(o,"src","types.ts");if(t==="clerk"){wt(ae.join(n,"better-auth.ts")),en(r,"clerk"),Zt(e,`# Clerk auth
338
+ `);return}let n=ge.join(o,"src","providers"),r=ge.join(o,"src","types.ts");if(t==="clerk"){Mt(ge.join(n,"better-auth.ts")),un(r,"clerk"),dn(e,`# Clerk auth
332
339
  CLERK_PUBLISHABLE_KEY=
333
340
  CLERK_SECRET_KEY=
334
- `);return}if(t==="betterauth"){wt(ae.join(n,"clerk.ts")),en(r,"better-auth"),Zt(e,`# Better Auth
341
+ `);return}if(t==="betterauth"){Mt(ge.join(n,"clerk.ts")),un(r,"better-auth"),dn(e,`# Better Auth
335
342
  BETTER_AUTH_SECRET=
336
343
  BETTER_AUTH_URL=http://localhost:3000
337
- `);return}}var Xe=[{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"}],Zo=new Set(Xe.map(e=>e.id));function nn(e){return Xe.find(t=>t.id===e)}function on(e){if(!e)return[];let t=e.split(",").map(r=>r.trim().toLowerCase()).filter(Boolean);if(t.includes("none"))return[];let o=[],n=new Set;for(let r of t)Zo.has(r)&&!n.has(r)&&(o.push(r),n.add(r));return o}import pe from"fs";import ce from"path";function er(e,t){let o=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
344
+ `);return}}var nt=[{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"}],fr=new Set(nt.map(e=>e.id));function gn(e){return nt.find(t=>t.id===e)}function fn(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)fr.has(r)&&!n.has(r)&&(o.push(r),n.add(r));return o}import ye from"fs";import fe from"path";function yr(e,t){let o=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
338
345
  // Generated by create-sailor \u2014 OAuth callback for ${e.name}
339
346
  // Primary auth provider: ${t}
340
347
  // Docs: ${e.docs}`,n={wechat:` const tokenRes = await fetch(
@@ -459,7 +466,7 @@ ${n[e.id]}
459
466
  void state;
460
467
  return NextResponse.redirect(new URL("/dashboard", req.url));
461
468
  }
462
- `}function tr(e){return`"use client";
469
+ `}function Sr(e){return`"use client";
463
470
 
464
471
  /**
465
472
  * SocialLoginButtons \u2014 generated by create-sailor.
@@ -502,17 +509,23 @@ export function SocialLoginButtons() {
502
509
  </div>
503
510
  );
504
511
  }
505
- `}function rn(e){pe.mkdirSync(e,{recursive:!0})}function nr(e,t){let o=ce.join(e,".env.example");pe.existsSync(o)?pe.appendFileSync(o,`
506
- `+t):pe.writeFileSync(o,t)}function or(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,o=e.envVars.map(n=>`${n}=`).join(`
512
+ `}function yn(e){ye.mkdirSync(e,{recursive:!0})}function Er(e,t){let o=fe.join(e,".env.example");ye.existsSync(o)?ye.appendFileSync(o,`
513
+ `+t):ye.writeFileSync(o,t)}function hr(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,o=e.envVars.map(n=>`${n}=`).join(`
507
514
  `);return`${t}
508
515
  ${o}
509
- `}async function sn(e,t,o){if(!t||t.length===0)return;let n=ce.join(e,"apps","web");if(!pe.existsSync(n))return;let r=new Set,s=[];for(let d of t){if(r.has(d))continue;r.add(d);let m=nn(d);m&&s.push(m)}if(s.length===0)return;for(let d of s)nr(e,or(d));let a=ce.join(n,"src","app","api","auth","callback");for(let d of s){let m=ce.join(a,d.id);rn(m);let E=ce.join(m,"route.ts");pe.writeFileSync(E,er(d,o))}let c=ce.join(n,"src","components","auth");rn(c);let i=ce.join(c,"SocialLoginButtons.tsx");pe.writeFileSync(i,tr(s))}import I from"fs";import _ from"path";var rr=_.join("apps","web"),Nt=_.join("src","components","compliance"),ze=_.join("src","app","[locale]");function V(e){return _.join(e,rr)}function sr(e){I.mkdirSync(e,{recursive:!0})}function O(e,t){sr(_.dirname(e)),I.writeFileSync(e,t,"utf8")}function xt(e,t){let o=_.join(e,".env.example");if(I.existsSync(o)){if(I.readFileSync(o,"utf8").includes(t.split(`
510
- `)[0]??""))return;I.appendFileSync(o,`
516
+ `}async function Sn(e,t,o){if(!t||t.length===0)return;let n=fe.join(e,"apps","web");if(!ye.existsSync(n))return;let r=new Set,s=[];for(let d of t){if(r.has(d))continue;r.add(d);let u=gn(d);u&&s.push(u)}if(s.length===0)return;for(let d of s)Er(e,hr(d));let a=fe.join(n,"src","app","api","auth","callback");for(let d of s){let u=fe.join(a,d.id);yn(u);let S=fe.join(u,"route.ts");ye.writeFileSync(S,yr(d,o))}let c=fe.join(n,"src","components","auth");yn(c);let i=fe.join(c,"SocialLoginButtons.tsx");ye.writeFileSync(i,Sr(s))}import oe from"fs";import Dt from"path";var vt=[{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 En(e){return vt.find(t=>t.id===e)}var Ea=vt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function hn(e){return oe.existsSync(e)?oe.readFileSync(e,"utf-8"):null}function vr(e,t){let o=Dt.join(e,".env.example"),n=hn(o);if(n===null)return;let r=`# Cache: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(a=>`${a}=""`),""].join(`
517
+ `);oe.appendFileSync(o,s)}function _r(e,t,o){let n=Dt.join(e,".env.example"),r=hn(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?oe.writeFileSync(n,r.replace(s,`${t}="${o}"`)):oe.appendFileSync(n,`${t}="${o}"
518
+ `)}async function vn(e,t,o){let n=Dt.join(e,"packages","cache");if(t==="none"){oe.existsSync(n)&&oe.rmSync(n,{recursive:!0,force:!0});return}let r=En(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${vt.map(s=>s.id).join(", ")}`);oe.existsSync(n)&&(vr(e,r),_r(e,"CACHE_PROVIDER",t))}var _t=[{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 _n(e){return _t.find(t=>t.id===e)}var Ia=_t.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import J from"fs";import Ft from"path";function G(e,t){let o=Ft.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(i=>`${i}=""`),""].filter(i=>i!==null).join(`
519
+ `);J.appendFileSync(o,c)}function H(e,t,o){let n=Ft.join(e,".env.example");if(!J.existsSync(n))return;let r=J.readFileSync(n,"utf-8"),s=`${t}="${o}"`,a=new RegExp(`^${t}=.*$`,"m");if(a.test(r)){J.writeFileSync(n,r.replace(a,s));return}let c=r.endsWith(`
520
+ `)?"":`
521
+ `;J.appendFileSync(n,`${c}${s}
522
+ `)}function B(e,t){let o=Ft.join(e,"packages",t);J.existsSync(o)&&J.rmSync(o,{recursive:!0,force:!0})}async function Pn(e,t,o="global"){let n=_n(t);if(!n)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${_t.map(r=>r.id).join(", ")}`);if(n.id==="none"){B(e,"captcha");return}n.envVars.length>0&&G(e,{category:"Captcha",name:n.name,envVars:n.envVars,docs:n.docs}),H(e,"CAPTCHA_PROVIDER",n.id)}import bt from"fs";import Pr from"path";var Pt=[{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 bn(e){return Pt.find(t=>t.id===e)}var Ta=Pt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function In(e,t,o="global"){let n=bn(t);if(!n)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${Pt.map(s=>s.id).join(", ")}`);let r=Pr.join(e,"apps","studio");if(n.id==="none"){B(e,"sanity"),bt.existsSync(r)&&bt.rmSync(r,{recursive:!0,force:!0});return}n.id!=="sanity"&&(B(e,"sanity"),bt.existsSync(r)&&bt.rmSync(r,{recursive:!0,force:!0})),n.envVars.length>0&&G(e,{category:"CMS",name:n.name,envVars:n.envVars,docs:n.docs}),H(e,"CMS_PROVIDER",n.id)}import A from"fs";import I from"path";var br=I.join("apps","web"),jt=I.join("src","components","compliance"),ot=I.join("src","app","[locale]");function W(e){return I.join(e,br)}function Ir(e){A.mkdirSync(e,{recursive:!0})}function Y(e,t){Ir(I.dirname(e)),A.writeFileSync(e,t,"utf8")}function Vt(e,t){let o=I.join(e,".env.example");if(A.existsSync(o)){if(A.readFileSync(o,"utf8").includes(t.split(`
523
+ `)[0]??""))return;A.appendFileSync(o,`
511
524
  `+t+`
512
- `)}else I.writeFileSync(o,t+`
513
- `)}var Qe=`> **TEMPLATE \u2014 NOT LEGAL ADVICE.** This document is a boilerplate scaffold only.
525
+ `)}else A.writeFileSync(o,t+`
526
+ `)}var rt=`> **TEMPLATE \u2014 NOT LEGAL ADVICE.** This document is a boilerplate scaffold only.
514
527
  > Consult a qualified lawyer in every jurisdiction you operate in before publishing.
515
- > \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`,ir=`import Link from "next/link";
528
+ > \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`,Cr=`import Link from "next/link";
516
529
  import { IcpFooter } from "@/components/compliance/IcpFooter";
517
530
  import { PublicSecurityFooter } from "@/components/compliance/PublicSecurityFooter";
518
531
 
@@ -563,7 +576,7 @@ export function Footer({ region = "global" }: FooterProps) {
563
576
  </footer>
564
577
  );
565
578
  }
566
- `,ar=`export function IcpFooter() {
579
+ `,Ar=`export function IcpFooter() {
567
580
  const icp = process.env.NEXT_PUBLIC_ICP_BEIAN;
568
581
  if (!icp) return null;
569
582
  return (
@@ -577,7 +590,7 @@ export function Footer({ region = "global" }: FooterProps) {
577
590
  </a>
578
591
  );
579
592
  }
580
- `,cr=`export function PublicSecurityFooter() {
593
+ `,wr=`export function PublicSecurityFooter() {
581
594
  const psb = process.env.NEXT_PUBLIC_PSB_BEIAN;
582
595
  const psbCode = process.env.NEXT_PUBLIC_PSB_CODE;
583
596
  if (!psb) return null;
@@ -594,7 +607,7 @@ export function Footer({ region = "global" }: FooterProps) {
594
607
  </a>
595
608
  );
596
609
  }
597
- `,pr=`"use client";
610
+ `,Rr=`"use client";
598
611
 
599
612
  import { useCallback, useEffect, useState } from "react";
600
613
 
@@ -821,7 +834,7 @@ function CategoryRow({ id, title, description, checked, disabled, onChange }: Ca
821
834
  </label>
822
835
  );
823
836
  }
824
- `,lr=`interface AigcDisclaimerProps {
837
+ `,Nr=`interface AigcDisclaimerProps {
825
838
  className?: string;
826
839
  }
827
840
 
@@ -841,13 +854,13 @@ export function AigcDisclaimer({ className }: AigcDisclaimerProps) {
841
854
  </div>
842
855
  );
843
856
  }
844
- `,dr=`---
857
+ `,xr=`---
845
858
  title: Privacy Policy / \u9690\u79C1\u653F\u7B56
846
859
  description: How {{COMPANY_NAME}} collects, uses, shares, and protects personal information.
847
860
  lastUpdated: 2026-01-01
848
861
  ---
849
862
 
850
- ${Qe}
863
+ ${rt}
851
864
 
852
865
  # Privacy Policy / \u9690\u79C1\u653F\u7B56
853
866
 
@@ -986,13 +999,13 @@ or in-app notification before the change takes effect.
986
999
  **Data Controller / \u6570\u636E\u63A7\u5236\u8005:** {{COMPANY_NAME}}
987
1000
  **Address / \u5730\u5740:** {{COMPANY_ADDRESS}}
988
1001
  **Email / \u90AE\u7BB1:** {{COMPANY_CONTACT_EMAIL}}
989
- `,ur=`---
1002
+ `,kr=`---
990
1003
  title: Terms of Service / \u670D\u52A1\u6761\u6B3E
991
1004
  description: Terms governing your use of {{COMPANY_NAME}}.
992
1005
  lastUpdated: 2026-01-01
993
1006
  ---
994
1007
 
995
- ${Qe}
1008
+ ${rt}
996
1009
 
997
1010
  # Terms of Service / \u670D\u52A1\u6761\u6B3E
998
1011
 
@@ -1105,13 +1118,13 @@ conflict-of-laws principles. Disputes shall be resolved in the competent courts
1105
1118
  ## 11. Contact / \u8054\u7CFB\u65B9\u5F0F
1106
1119
 
1107
1120
  {{COMPANY_NAME}} \xB7 {{COMPANY_ADDRESS}} \xB7 {{COMPANY_CONTACT_EMAIL}}
1108
- `,mr=`---
1121
+ `,Tr=`---
1109
1122
  title: AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
1110
1123
  description: Disclosure required by \u7F51\u4FE1\u529E\u300A\u751F\u6210\u5F0F\u4EBA\u5DE5\u667A\u80FD\u670D\u52A1\u7BA1\u7406\u6682\u884C\u529E\u6CD5\u300B
1111
1124
  lastUpdated: 2026-01-01
1112
1125
  ---
1113
1126
 
1114
- ${Qe}
1127
+ ${rt}
1115
1128
 
1116
1129
  # AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
1117
1130
 
@@ -1187,13 +1200,13 @@ human professional.
1187
1200
 
1188
1201
  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
1189
1202
  \u7528\u4E8E\u533B\u7597\u3001\u6CD5\u5F8B\u3001\u91D1\u878D\u6216\u5B89\u5168\u6538\u5173\u7684\u51B3\u7B56\u3002
1190
- `,gr=`---
1203
+ `,Or=`---
1191
1204
  title: Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
1192
1205
  description: Notice of cross-border transfer of personal information, per PIPL.
1193
1206
  lastUpdated: 2026-01-01
1194
1207
  ---
1195
1208
 
1196
- ${Qe}
1209
+ ${rt}
1197
1210
 
1198
1211
  # Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
1199
1212
 
@@ -1252,13 +1265,13 @@ Refusal may limit your ability to use features that rely on overseas services.
1252
1265
  - \u4F20\u8F93\u4E2D\u52A0\u5BC6 (TLS 1.2+) \u53CA\u9759\u6001\u52A0\u5BC6 (AES-256)\u3002
1253
1266
  - \u5408\u540C\u6761\u6B3E\u8981\u6C42\u5883\u5916\u63A5\u6536\u65B9\u63D0\u4F9B\u7B49\u540C\u4E8E PIPL \u7684\u4FDD\u62A4\u3002
1254
1267
  - \u8BBF\u95EE\u63A7\u5236\u3001\u5BA1\u8BA1\u65E5\u5FD7\u548C\u8FDD\u89C4\u901A\u77E5\u7A0B\u5E8F\u3002
1255
- `,fr=`---
1268
+ `,Ur=`---
1256
1269
  title: Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
1257
1270
  description: Itemized list of personal information collected, per PIPL Article 17.
1258
1271
  lastUpdated: 2026-01-01
1259
1272
  ---
1260
1273
 
1261
- ${Qe}
1274
+ ${rt}
1262
1275
 
1263
1276
  # Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
1264
1277
 
@@ -1294,19 +1307,19 @@ To exercise your rights (access, rectify, delete, export, withdraw consent), con
1294
1307
  **{{COMPANY_CONTACT_EMAIL}}**.
1295
1308
 
1296
1309
  \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
1297
- `;async function yr(e,t){let o=V(e);if(!I.existsSync(o))return;let n=_.join(o,"src","components","compliance","Footer.tsx");O(n,ir);let r=_.join(o,"src","components","compliance","README.md");O(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(`
1298
- `))}async function Sr(e,t){let o=V(e);if(!I.existsSync(o))return;let n=_.join(o,"src","components","compliance","CookieBanner.tsx");O(n,pr)}async function Er(e,t){let o=V(e);if(!I.existsSync(o))return;let n=_.join(o,ze,"privacy","page.mdx");O(n,dr)}async function hr(e,t){let o=V(e);if(!I.existsSync(o))return;let n=_.join(o,ze,"terms","page.mdx");O(n,ur)}async function vr(e){let t=V(e);if(!I.existsSync(t))return;let o=_.join(t,Nt,"IcpFooter.tsx");O(o,ar),xt(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(`
1299
- `))}async function _r(e){let t=V(e);if(!I.existsSync(t))return;let o=_.join(t,Nt,"PublicSecurityFooter.tsx");O(o,cr),xt(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(`
1300
- `))}async function Pr(e){let t=V(e);if(!I.existsSync(t))return;let o=_.join(t,Nt,"AigcDisclaimer.tsx");O(o,lr),xt(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(`
1301
- `))}async function Ir(e){let t=V(e);if(!I.existsSync(t))return;let o=_.join(t,ze,"aigc-disclosure","page.mdx");O(o,mr)}async function Cr(e){let t=V(e);if(!I.existsSync(t))return;let o=_.join(t,ze,"cross-border-data","page.mdx");O(o,gr)}async function br(e){let t=V(e);if(!I.existsSync(t))return;let o=_.join(t,ze,"pii-collection","page.mdx");O(o,fr)}async function an(e,t){try{await yr(e,t),await Sr(e,t),await Er(e,t),await hr(e,t),(t==="cn"||t==="hybrid")&&(await vr(e),await _r(e),await Pr(e),await Ir(e),await Cr(e),await br(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 Ar from"fs";import Rr from"path";async function cn(e,t){let o=Rr.join(e,"nebutra.config.json");Ar.writeFileSync(o,JSON.stringify(t,null,2)+`
1302
- `)}import z from"fs";import Tt from"path";function wr(e){z.existsSync(e)&&z.rmSync(e,{recursive:!0,force:!0})}function pn(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function Nr(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function ln(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 xr(e,t){let o=Tt.join(e,".env.example");z.existsSync(o)?z.appendFileSync(o,`
1303
- `+t):z.writeFileSync(o,t)}async function dn(e,t,o){let n=Tt.join(e,"packages","db");if(t==="none"){wr(n);return}let r=Tt.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",xr(e,`# Database (${t})
1310
+ `;async function Lr(e,t){let o=W(e);if(!A.existsSync(o))return;let n=I.join(o,"src","components","compliance","Footer.tsx");Y(n,Cr);let r=I.join(o,"src","components","compliance","README.md");Y(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(`
1311
+ `))}async function Mr(e,t){let o=W(e);if(!A.existsSync(o))return;let n=I.join(o,"src","components","compliance","CookieBanner.tsx");Y(n,Rr)}async function Dr(e,t){let o=W(e);if(!A.existsSync(o))return;let n=I.join(o,ot,"privacy","page.mdx");Y(n,xr)}async function Fr(e,t){let o=W(e);if(!A.existsSync(o))return;let n=I.join(o,ot,"terms","page.mdx");Y(n,kr)}async function jr(e){let t=W(e);if(!A.existsSync(t))return;let o=I.join(t,jt,"IcpFooter.tsx");Y(o,Ar),Vt(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(`
1312
+ `))}async function Vr(e){let t=W(e);if(!A.existsSync(t))return;let o=I.join(t,jt,"PublicSecurityFooter.tsx");Y(o,wr),Vt(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(`
1313
+ `))}async function Kr(e){let t=W(e);if(!A.existsSync(t))return;let o=I.join(t,jt,"AigcDisclaimer.tsx");Y(o,Nr),Vt(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(`
1314
+ `))}async function Br(e){let t=W(e);if(!A.existsSync(t))return;let o=I.join(t,ot,"aigc-disclosure","page.mdx");Y(o,Tr)}async function Yr(e){let t=W(e);if(!A.existsSync(t))return;let o=I.join(t,ot,"cross-border-data","page.mdx");Y(o,Or)}async function $r(e){let t=W(e);if(!A.existsSync(t))return;let o=I.join(t,ot,"pii-collection","page.mdx");Y(o,Ur)}async function Cn(e,t){try{await Lr(e,t),await Mr(e,t),await Dr(e,t),await Fr(e,t),(t==="cn"||t==="hybrid")&&(await jr(e),await Vr(e),await Kr(e),await Br(e),await Yr(e),await $r(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 qr from"fs";import Gr from"path";async function An(e,t){let o=Gr.join(e,"nebutra.config.json");qr.writeFileSync(o,JSON.stringify(t,null,2)+`
1315
+ `)}import re from"fs";import Kt from"path";function Hr(e){re.existsSync(e)&&re.rmSync(e,{recursive:!0,force:!0})}function wn(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function Wr(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function Rn(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 Xr(e,t){let o=Kt.join(e,".env.example");re.existsSync(o)?re.appendFileSync(o,`
1316
+ `+t):re.writeFileSync(o,t)}async function Nn(e,t,o){let n=Kt.join(e,"packages","db");if(t==="none"){Hr(n);return}let r=Kt.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",Xr(e,`# Database (${t})
1304
1317
  DATABASE_URL="${s}"
1305
- `),!z.existsSync(r))return;let a=z.readFileSync(r,"utf8"),c=a;t==="mysql"?(c=pn(c,"mysql"),c=ln(c)):t==="sqlite"&&(c=pn(c,"sqlite"),c=Nr(c),c=ln(c)),c!==a&&z.writeFileSync(r,c)}import Je from"fs";import N from"path";import{fileURLToPath as Tr}from"url";var kr=Tr(import.meta.url),Or=N.dirname(kr);async function un(e,t){if(t==="none")return;let o=N.join(Or,"../../templates/deploy");t==="vercel"?await Je.promises.copyFile(N.join(o,"vercel.json"),N.join(e,"vercel.json")):t==="railway"?await Je.promises.copyFile(N.join(o,"railway.toml"),N.join(e,"railway.toml")):t==="cloudflare"?await Je.promises.copyFile(N.join(o,"wrangler.toml"),N.join(e,"wrangler.toml")):t==="selfhost"&&(await Je.promises.copyFile(N.join(o,"docker-compose.yml"),N.join(e,"docker-compose.yml")),await Je.promises.copyFile(N.join(o,"Dockerfile.web"),N.join(e,"Dockerfile.web")))}import Q from"fs";import le from"path";import{fileURLToPath as Ur}from"url";var Lr=Ur(import.meta.url),mn=le.dirname(Lr),Mr=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml)$/;function Dr(e){let t=[le.join(mn,"..","templates","docs",e),le.join(mn,"..","..","templates","docs",e)];for(let o of t)if(Q.existsSync(o))return o;return t[0]}async function gn(e,t){if(t.framework==="none")return;let o=(t.framework==="fumadocs","fumadocs"),n=Dr(o),r=le.join(e,"apps","docs");if(!Q.existsSync(n))throw new Error(`Docs template not found: ${n}`);fn(n,r),yn(r,{"{PRODUCT_NAME}":t.projectName})}function fn(e,t){Q.mkdirSync(t,{recursive:!0});for(let o of Q.readdirSync(e,{withFileTypes:!0})){let n=le.join(e,o.name),r=le.join(t,o.name);o.isDirectory()?fn(n,r):Q.copyFileSync(n,r)}}function yn(e,t){for(let o of Q.readdirSync(e,{withFileTypes:!0})){let n=le.join(e,o.name);if(o.isDirectory())yn(n,t);else if(Mr.test(o.name)){let r=Q.readFileSync(n,"utf-8");for(let[s,a]of Object.entries(t))r=r.split(s).join(a);Q.writeFileSync(n,r)}}}import ue from"fs";import de from"path";var mt=[{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 Sn(e){return mt.find(t=>t.id===e)}var ia=mt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var me="@nebutra/email";function kt(e,t){ue.mkdirSync(de.dirname(e),{recursive:!0}),ue.writeFileSync(e,t)}function jr(e,t){let o=de.join(e,".env.example");ue.existsSync(o)?ue.appendFileSync(o,`
1306
- `+t):ue.writeFileSync(o,t)}function Fr(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
1318
+ `),!re.existsSync(r))return;let a=re.readFileSync(r,"utf8"),c=a;t==="mysql"?(c=wn(c,"mysql"),c=Rn(c)):t==="sqlite"&&(c=wn(c,"sqlite"),c=Wr(c),c=Rn(c)),c!==a&&re.writeFileSync(r,c)}import st from"fs";import D from"path";import{fileURLToPath as zr}from"url";var Qr=zr(import.meta.url),Jr=D.dirname(Qr);async function xn(e,t){if(t==="none")return;let o=D.join(Jr,"../../templates/deploy");t==="vercel"?await st.promises.copyFile(D.join(o,"vercel.json"),D.join(e,"vercel.json")):t==="railway"?await st.promises.copyFile(D.join(o,"railway.toml"),D.join(e,"railway.toml")):t==="cloudflare"?await st.promises.copyFile(D.join(o,"wrangler.toml"),D.join(e,"wrangler.toml")):t==="selfhost"&&(await st.promises.copyFile(D.join(o,"docker-compose.yml"),D.join(e,"docker-compose.yml")),await st.promises.copyFile(D.join(o,"Dockerfile.web"),D.join(e,"Dockerfile.web")))}import se from"fs";import Se from"path";import{fileURLToPath as Zr}from"url";var es=Zr(import.meta.url),kn=Se.dirname(es),ts=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml)$/;function ns(e){let t=[Se.join(kn,"..","templates","docs",e),Se.join(kn,"..","..","templates","docs",e)];for(let o of t)if(se.existsSync(o))return o;return t[0]}async function Tn(e,t){if(t.framework==="none")return;let o=(t.framework==="fumadocs","fumadocs"),n=ns(o),r=Se.join(e,"apps","docs");if(!se.existsSync(n))throw new Error(`Docs template not found: ${n}`);On(n,r),Un(r,{"{PRODUCT_NAME}":t.projectName})}function On(e,t){se.mkdirSync(t,{recursive:!0});for(let o of se.readdirSync(e,{withFileTypes:!0})){let n=Se.join(e,o.name),r=Se.join(t,o.name);o.isDirectory()?On(n,r):se.copyFileSync(n,r)}}function Un(e,t){for(let o of se.readdirSync(e,{withFileTypes:!0})){let n=Se.join(e,o.name);if(o.isDirectory())Un(n,t);else if(ts.test(o.name)){let r=se.readFileSync(n,"utf-8");for(let[s,a]of Object.entries(t))r=r.split(s).join(a);se.writeFileSync(n,r)}}}import he from"fs";import Ee from"path";var It=[{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 Ln(e){return It.find(t=>t.id===e)}var nc=It.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var ve="@nebutra/email";function Bt(e,t){he.mkdirSync(Ee.dirname(e),{recursive:!0}),he.writeFileSync(e,t)}function os(e,t){let o=Ee.join(e,".env.example");he.existsSync(o)?he.appendFileSync(o,`
1319
+ `+t):he.writeFileSync(o,t)}function rs(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
1307
1320
  `);return`${t}
1308
1321
  ${o}
1309
- `}var Vr=`/**
1322
+ `}var ss=`/**
1310
1323
  * Public inputs accepted by the \`sendEmail\` wrapper.
1311
1324
  * Keep the surface minimal \u2014 individual providers may accept more, but
1312
1325
  * consumers should code against this shape for portability.
@@ -1326,8 +1339,8 @@ export interface SendEmailResult {
1326
1339
  /** Raw provider response \u2014 useful for debugging, not a stable contract. */
1327
1340
  raw?: unknown;
1328
1341
  }
1329
- `;function Kr(){return`/**
1330
- * @${me.slice(1)} \u2014 Resend transactional email wrapper.
1342
+ `;function is(){return`/**
1343
+ * @${ve.slice(1)} \u2014 Resend transactional email wrapper.
1331
1344
  *
1332
1345
  * Docs: https://resend.com/docs
1333
1346
  */
@@ -1365,8 +1378,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1365
1378
  }
1366
1379
 
1367
1380
  export type { SendEmailInput, SendEmailResult } from "./types.js";
1368
- `}function Yr(){return`/**
1369
- * @${me.slice(1)} \u2014 Postmark transactional email wrapper.
1381
+ `}function as(){return`/**
1382
+ * @${ve.slice(1)} \u2014 Postmark transactional email wrapper.
1370
1383
  *
1371
1384
  * Docs: https://postmarkapp.com/developer
1372
1385
  */
@@ -1403,8 +1416,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1403
1416
  }
1404
1417
 
1405
1418
  export type { SendEmailInput, SendEmailResult } from "./types.js";
1406
- `}function Br(){return`/**
1407
- * @${me.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1419
+ `}function cs(){return`/**
1420
+ * @${ve.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1408
1421
  *
1409
1422
  * Docs: https://docs.aws.amazon.com/ses
1410
1423
  */
@@ -1459,8 +1472,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1459
1472
  }
1460
1473
 
1461
1474
  export type { SendEmailInput, SendEmailResult } from "./types.js";
1462
- `}function $r(){return`/**
1463
- * @${me.slice(1)} \u2014 \u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001 (Aliyun DirectMail) wrapper.
1475
+ `}function ps(){return`/**
1476
+ * @${ve.slice(1)} \u2014 \u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001 (Aliyun DirectMail) wrapper.
1464
1477
  *
1465
1478
  * Docs: https://help.aliyun.com/product/29412.html
1466
1479
  */
@@ -1509,8 +1522,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1509
1522
  }
1510
1523
 
1511
1524
  export type { SendEmailInput, SendEmailResult } from "./types.js";
1512
- `}function qr(){return`/**
1513
- * @${me.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1525
+ `}function ls(){return`/**
1526
+ * @${ve.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1514
1527
  *
1515
1528
  * Docs: https://cloud.tencent.com/document/product/1288
1516
1529
  */
@@ -1557,8 +1570,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1557
1570
  }
1558
1571
 
1559
1572
  export type { SendEmailInput, SendEmailResult } from "./types.js";
1560
- `}function Gr(){return`/**
1561
- * @${me.slice(1)} \u2014 \u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1 via SMTP (nodemailer).
1573
+ `}function ds(){return`/**
1574
+ * @${ve.slice(1)} \u2014 \u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1 via SMTP (nodemailer).
1562
1575
  *
1563
1576
  * Docs: https://qiye.163.com/help
1564
1577
  */
@@ -1595,21 +1608,23 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1595
1608
  }
1596
1609
 
1597
1610
  export type { SendEmailInput, SendEmailResult } from "./types.js";
1598
- `}function Hr(e){switch(e){case"resend":return Kr();case"postmark":return Yr();case"ses":return Br();case"aliyun-dm":return $r();case"tencent-ses":return qr();case"netease":return Gr();case"none":return`export {};
1599
- `}}function Wr(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:me,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)+`
1600
- `}async function En(e,t,o){if(t==="none")return;let n=Sn(t);if(!n)throw new Error(`Unknown email provider "${t}". Valid ids: ${mt.map(a=>a.id).join(", ")}`);let r=de.join(e,"packages","email"),s=de.join(r,"src");ue.existsSync(s)&&ue.rmSync(s,{recursive:!0,force:!0}),kt(de.join(r,"package.json"),Wr(n)),kt(de.join(s,"types.ts"),Vr),kt(de.join(s,"index.ts"),Hr(n.id)),jr(e,Fr(n))}import vn from"crypto";import Ze from"fs";import hn from"path";function ge(e){return vn.randomBytes(e).toString("base64").replace(/=+$/,"")}function Xr(e){return vn.randomBytes(e).toString("hex")}function zr(){return{AUTH_SECRET:ge(32),NEXTAUTH_SECRET:ge(32),BETTER_AUTH_SECRET:ge(32),JWT_SECRET:ge(32),WEBHOOK_SECRET:Xr(16),ENCRYPTION_KEY:ge(32),API_SECRET_KEY:ge(32),SESSION_SECRET:ge(32)}}function Qr(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Jr(e,t,o){let n=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=Qr(o);return e.replace(n,`${t}="${r}"`)}async function _n(e){let t=hn.join(e,".env.example"),o=hn.join(e,".env.local");if(!Ze.existsSync(t))return null;try{let n=Ze.readFileSync(t,"utf8"),r=zr(),a=Ze.existsSync(o)?Ze.readFileSync(o,"utf8"):n;for(let c of Object.keys(r))a=Jr(a,c,r[c]);return Ze.writeFileSync(o,a),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}`)}}import gt from"fs";import Pn from"path";async function In(e,t){let o=`# Automatically injected by create-sailor
1611
+ `}function us(e){switch(e){case"resend":return is();case"postmark":return as();case"ses":return cs();case"aliyun-dm":return ps();case"tencent-ses":return ls();case"netease":return ds();case"none":return`export {};
1612
+ `}}function ms(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:ve,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)+`
1613
+ `}async function Mn(e,t,o){if(t==="none")return;let n=Ln(t);if(!n)throw new Error(`Unknown email provider "${t}". Valid ids: ${It.map(a=>a.id).join(", ")}`);let r=Ee.join(e,"packages","email"),s=Ee.join(r,"src");he.existsSync(s)&&he.rmSync(s,{recursive:!0,force:!0}),Bt(Ee.join(r,"package.json"),ms(n)),Bt(Ee.join(s,"types.ts"),ss),Bt(Ee.join(s,"index.ts"),us(n.id)),os(e,rs(n))}import Ct from"fs";import Dn from"path";async function Fn(e,t){let o=`# Automatically injected by create-sailor
1601
1614
  DATABASE_URL="${String(t.databaseUrl)}"
1602
1615
 
1603
1616
  NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="${String(t.clerkPublishable)}"
1604
1617
  CLERK_SECRET_KEY="${String(t.clerkSecret)}"
1605
1618
 
1606
1619
  NEXT_PUBLIC_SITE_URL="http://localhost:3000"
1607
- `,n=Pn.join(e,".env"),r=Pn.join(e,".env.local");!gt.existsSync(n)&&!gt.existsSync(r)?gt.writeFileSync(r,o):gt.appendFileSync(r,`
1608
- `+o)}import{execSync as Zr}from"child_process";import K from"fs";import ke from"path";import es from"ignore";var ts={mirror:{repo:process.env.SAILOR_TEMPLATE_REPO||"Nebutra/Sailor-Template",ref:process.env.SAILOR_TEMPLATE_REF||"main",applyIgnore:!1},main:{repo:"Nebutra/Nebutra-Sailor",ref:"main",applyIgnore:!0}};function ns(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function Cn(e,t,o){let n=K.readdirSync(t,{withFileTypes:!0});for(let r of n){if(r.name==="node_modules"||r.name===".git")continue;let s=ke.join(t,r.name),a=ke.relative(e,s).split(ke.sep).join("/");r.isDirectory()?(o.push(a+"/"),Cn(e,s,o)):o.push(a)}}function os(e){let t=ke.join(e,".templateignore");if(!K.existsSync(t))return;let o=K.readFileSync(t,"utf8"),n=es().add(o),r=[];Cn(e,e,r);let s=r.map(i=>i.endsWith("/")?i.slice(0,-1):i),a=new Set(n.filter(s)),c=s.filter(i=>!a.has(i)).sort((i,d)=>d.split("/").length-i.split("/").length);for(let i of c){let d=ke.join(e,i);try{K.existsSync(d)&&K.rmSync(d,{recursive:!0,force:!0})}catch{}}try{K.existsSync(t)&&K.rmSync(t,{force:!0})}catch{}}function rs(e,t){Zr(`set -o pipefail; curl -sSfL ${e} | tar -xz -C "${t}" --strip-components=1`,{stdio:"ignore",shell:"bash"})}async function bn(e){K.mkdirSync(e,{recursive:!0});let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],n;for(let r of o){let s=ts[r],a=ns(s.repo,s.ref);try{if(rs(a,e),s.applyIgnore)try{os(e)}catch(c){throw new Error(`Template cloned, but .templateignore processing failed: ${c instanceof Error?c.message:String(c)}`)}return}catch(c){n=c instanceof Error?c:new Error(String(c));try{let i=K.readdirSync(e);for(let d of i)K.rmSync(ke.join(e,d),{recursive:!0,force:!0})}catch{}}}throw new Error(`Failed to download the template from any source. Last error: ${n?.message??"unknown"}
1620
+ `,n=Dn.join(e,".env"),r=Dn.join(e,".env.local");!Ct.existsSync(n)&&!Ct.existsSync(r)?Ct.writeFileSync(r,o):Ct.appendFileSync(r,`
1621
+ `+o)}import Vn from"crypto";import it from"fs";import jn from"path";function _e(e){return Vn.randomBytes(e).toString("base64").replace(/=+$/,"")}function gs(e){return Vn.randomBytes(e).toString("hex")}function fs(){return{AUTH_SECRET:_e(32),NEXTAUTH_SECRET:_e(32),BETTER_AUTH_SECRET:_e(32),JWT_SECRET:_e(32),WEBHOOK_SECRET:gs(16),ENCRYPTION_KEY:_e(32),API_SECRET_KEY:_e(32),SESSION_SECRET:_e(32)}}function ys(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Ss(e,t,o){let n=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=ys(o);return e.replace(n,`${t}="${r}"`)}async function Kn(e){let t=jn.join(e,".env.example"),o=jn.join(e,".env.local");if(!it.existsSync(t))return null;try{let n=it.readFileSync(t,"utf8"),r=fs(),a=it.existsSync(o)?it.readFileSync(o,"utf8"):n;for(let c of Object.keys(r))a=Ss(a,c,r[c]);return it.writeFileSync(o,a),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 At=[{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 Bn(e){return At.find(t=>t.id===e)}var fc=At.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Yn(e,t,o="global"){let n=Bn(t);if(!n)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${At.map(r=>r.id).join(", ")}`);if(n.id==="none"){B(e,"feature-flags");return}n.envVars.length>0&&G(e,{category:"Feature Flags",name:n.name,envVars:n.envVars,docs:n.docs}),H(e,"FEATURE_FLAGS_PROVIDER",n.id)}import{execFileSync as Es}from"child_process";import x from"fs";import hs from"os";import ie from"path";import vs from"ignore";var _s={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 Ps(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function bs(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function Is(e){return/^[0-9a-f]{7,40}$/i.test(e)}async function Cs(e,t){if(Is(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)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 Gn(e,t,o){let n=x.readdirSync(t,{withFileTypes:!0});for(let r of n){if(r.name==="node_modules"||r.name===".git")continue;let s=ie.join(t,r.name),a=ie.relative(e,s).split(ie.sep).join("/");r.isDirectory()?(o.push(a+"/"),Gn(e,s,o)):o.push(a)}}function As(e){let t=ie.join(e,".templateignore");if(!x.existsSync(t))return;let o=x.readFileSync(t,"utf8"),n=vs().add(o),r=[];Gn(e,e,r);let s=r.map(i=>i.endsWith("/")?i.slice(0,-1):i),a=new Set(n.filter(s)),c=s.filter(i=>!a.has(i)).sort((i,d)=>d.split("/").length-i.split("/").length);for(let i of c){let d=ie.join(e,i);try{x.existsSync(d)&&x.rmSync(d,{recursive:!0,force:!0})}catch{}}try{x.existsSync(t)&&x.rmSync(t,{force:!0})}catch{}}async function $n(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)`);x.writeFileSync(t,n);let r=x.statSync(t);if(r.size!==n.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${n.byteLength})`);return r.size}function qn(e,t){Es("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function Hn(e){try{let t=x.readdirSync(e);for(let o of t)x.rmSync(ie.join(e,o),{recursive:!0,force:!0})}catch{}}async function ws(e,t){let o=x.mkdtempSync(ie.join(hs.tmpdir(),"create-sailor-")),n=ie.join(o,"template.tar.gz");try{let r=await Cs(e.repo,e.ref);await $n(bs(e.repo,r),n),qn(n,t)}catch(r){if(!e.allowMutableFallback)throw r;Hn(t),await $n(Ps(e.repo,e.ref),n),qn(n,t)}finally{x.rmSync(o,{recursive:!0,force:!0})}}async function Wn(e){x.mkdirSync(e,{recursive:!0});let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],n;for(let r of o){let s=_s[r];try{if(await ws(s,e),s.applyIgnore)try{As(e)}catch(a){throw new Error(`Template cloned, but .templateignore processing failed: ${a instanceof Error?a.message:String(a)}`)}return}catch(a){n=a instanceof Error?a:new Error(String(a)),Hn(e)}}throw new Error(`Failed to download the template from any source. Last error: ${n?.message??"unknown"}
1609
1622
 
1610
- Ensure you have internet access and curl/tar installed.
1611
- You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import Oe from"fs";import R from"path";var An=[{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:""}],Ca=An.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Rn(e){return An.find(t=>t.id===e)}function ss(e){Oe.mkdirSync(e,{recursive:!0})}function Y(e,t){ss(R.dirname(e)),Oe.writeFileSync(e,t)}function et(e,t){let o=R.join(e,".env.example");Oe.existsSync(o)?Oe.appendFileSync(o,`
1612
- `+t):Oe.writeFileSync(o,t)}function is(e){let t=`import * as Sentry from "@sentry/nextjs";
1623
+ Ensure you have internet access and 'tar' installed.
1624
+ You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import Pe from"fs";import Yt from"path";async function Xn(e,t){let o=Yt.join(e,"packages","mcp");if(t==="off"){Pe.existsSync(o)&&Pe.rmSync(o,{recursive:!0,force:!0});let r=Yt.join(e,"packages","cli","src","commands","mcp-server.ts");Pe.existsSync(r)&&Pe.rmSync(r,{force:!0});return}let n=Yt.join(e,".env.example");if(Pe.existsSync(n)){let r=Pe.readFileSync(n,"utf-8"),s="# MCP Server (Agent-friendly API)";if(!r.includes(s)){let a=["","# =============================================",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(`
1625
+ `);Pe.appendFileSync(n,a)}}}import at from"fs";import zn from"path";async function Qn(e,t,o){let n=zn.join(e,"packages","metering"),r;if(t==="auto"?r=o!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){at.existsSync(n)&&at.rmSync(n,{recursive:!0,force:!0});return}let s=zn.join(e,".env.example");if(!at.existsSync(s))return;let a=at.readFileSync(s,"utf-8"),c="# Metering (usage-based billing)";if(!a.includes(c)){let i=["","# =============================================",c,"# Docs: see packages/metering/README.md","# =============================================","# ClickHouse-based metering pipeline for consumption billing.",'CLICKHOUSE_URL=""','CLICKHOUSE_USER="default"','CLICKHOUSE_PASSWORD=""','CLICKHOUSE_DATABASE="metering"',""].join(`
1626
+ `);at.appendFileSync(s,i)}}import He from"fs";import O from"path";var Jn=[{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:""}],Tc=Jn.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Zn(e){return Jn.find(t=>t.id===e)}function Rs(e){He.mkdirSync(e,{recursive:!0})}function X(e,t){Rs(O.dirname(e)),He.writeFileSync(e,t)}function ct(e,t){let o=O.join(e,".env.example");He.existsSync(o)?He.appendFileSync(o,`
1627
+ `+t):He.writeFileSync(o,t)}function Ns(e){let t=`import * as Sentry from "@sentry/nextjs";
1613
1628
 
1614
1629
  Sentry.init({
1615
1630
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
@@ -1652,14 +1667,14 @@ export async function register() {
1652
1667
  }
1653
1668
 
1654
1669
  export { captureRequestError as onRequestError } from "@sentry/nextjs";
1655
- `;Y(R.join(e,"sentry.client.config.ts"),t),Y(R.join(e,"sentry.server.config.ts"),o),Y(R.join(e,"sentry.edge.config.ts"),n),Y(R.join(e,"instrumentation.ts"),r)}function as(){return`# Sentry \u2014 error tracking + performance monitoring
1670
+ `;X(O.join(e,"sentry.client.config.ts"),t),X(O.join(e,"sentry.server.config.ts"),o),X(O.join(e,"sentry.edge.config.ts"),n),X(O.join(e,"instrumentation.ts"),r)}function xs(){return`# Sentry \u2014 error tracking + performance monitoring
1656
1671
  # Get your DSN from https://sentry.io/settings/projects/<project>/keys/
1657
1672
  SENTRY_DSN=
1658
1673
  NEXT_PUBLIC_SENTRY_DSN=
1659
1674
  SENTRY_ORG=
1660
1675
  SENTRY_PROJECT=
1661
1676
  SENTRY_AUTH_TOKEN=
1662
- `}function cs(e){let t=`/**
1677
+ `}function ks(e){let t=`/**
1663
1678
  * Next.js instrumentation hook \u2014 wires Datadog APM (dd-trace) into Node runtime.
1664
1679
  * Edge runtime is not supported by dd-trace; only nodejs is initialized.
1665
1680
  */
@@ -1707,7 +1722,7 @@ export function initDatadogRum(): void {
1707
1722
  });
1708
1723
  initialized = true;
1709
1724
  }
1710
- `;Y(R.join(e,"instrumentation.ts"),t),Y(R.join(e,"src","lib","monitoring","datadog-rum.ts"),o)}function ps(){return`# Datadog \u2014 APM + RUM
1725
+ `;X(O.join(e,"instrumentation.ts"),t),X(O.join(e,"src","lib","monitoring","datadog-rum.ts"),o)}function Ts(){return`# Datadog \u2014 APM + RUM
1711
1726
  # Server APM (dd-trace)
1712
1727
  DD_API_KEY=
1713
1728
  DD_APP_KEY=
@@ -1722,7 +1737,7 @@ NEXT_PUBLIC_DD_SITE=datadoghq.com
1722
1737
  NEXT_PUBLIC_DD_SERVICE=sailor-web
1723
1738
  NEXT_PUBLIC_DD_ENV=production
1724
1739
  NEXT_PUBLIC_DD_VERSION=
1725
- `}function ls(e){let t=`/**
1740
+ `}function Os(e){let t=`/**
1726
1741
  * Bugsnag server-side initialization.
1727
1742
  * Import this once at the top of your server entrypoint or a shared init module.
1728
1743
  */
@@ -1771,11 +1786,11 @@ export function getBugsnagErrorBoundary() {
1771
1786
  errorBoundary = plugin.createErrorBoundary(React) as typeof errorBoundary;
1772
1787
  return errorBoundary;
1773
1788
  }
1774
- `;Y(R.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),Y(R.join(e,"src","lib","monitoring","bugsnag.client.tsx"),o)}function ds(){return`# Bugsnag \u2014 error tracking
1789
+ `;X(O.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),X(O.join(e,"src","lib","monitoring","bugsnag.client.tsx"),o)}function Us(){return`# Bugsnag \u2014 error tracking
1775
1790
  BUGSNAG_API_KEY=
1776
1791
  NEXT_PUBLIC_BUGSNAG_API_KEY=
1777
1792
  APP_VERSION=
1778
- `}function us(e){Y(R.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1793
+ `}function Ls(e){X(O.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1779
1794
  /**
1780
1795
  * \u963F\u91CC\u4E91 ARMS (Application Real-time Monitoring Service) browser agent.
1781
1796
  * Injects the official JS agent via next/script.
@@ -1796,11 +1811,11 @@ export function ArmsScript() {
1796
1811
  />
1797
1812
  );
1798
1813
  }
1799
- `)}function ms(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1814
+ `)}function Ms(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1800
1815
  ALIYUN_ARMS_LICENSE_KEY=
1801
1816
  ALIYUN_ARMS_APP_NAME=
1802
1817
  NEXT_PUBLIC_ARMS_PID=
1803
- `}function gs(e){Y(R.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1818
+ `}function Ds(e){X(O.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1804
1819
  /**
1805
1820
  * \u542C\u4E91 Browser Agent (\u524D\u7AEF\u6027\u80FD\u76D1\u63A7).
1806
1821
  * Docs: https://www.tingyun.com/docs
@@ -1818,12 +1833,12 @@ export function TingYunScript() {
1818
1833
  />
1819
1834
  );
1820
1835
  }
1821
- `)}function fs(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1836
+ `)}function Fs(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1822
1837
  TINGYUN_LICENSE_KEY=
1823
1838
  NEXT_PUBLIC_TINGYUN_APP_KEY=
1824
- `}async function wn(e,t,o="global"){let n=Rn(t);if(!n||n.id==="none")return;let r=R.join(e,"apps","web");if(!Oe.existsSync(r))return;let s=n.id;try{switch(s){case"sentry":is(r),et(e,as());return;case"datadog":cs(r),et(e,ps());return;case"bugsnag":ls(r),et(e,ds());return;case"aliyun-arms":us(r),et(e,ms());return;case"tingyun":gs(r),et(e,fs());return;default:return}}catch(a){throw console.error(`Failed to apply monitoring selection "${t}":`,a),new Error(`Monitoring scaffold for "${t}" failed \u2014 see stderr for details.`)}}import Ot from"fs";import ys from"path";async function Nn(e,t){let o=ys.join(e,"package.json");if(Ot.existsSync(o)){let n=Ot.readFileSync(o,"utf8"),r=JSON.parse(n);r.name=t,r.version="0.1.0",Ot.writeFileSync(o,JSON.stringify(r,null,2)+`
1825
- `)}}import G from"fs";import tt from"path";var Ss=["stripe","lemonsqueezy","chinapay","polar"];function xn(e){G.existsSync(e)&&G.rmSync(e,{recursive:!0,force:!0})}function Es(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function hs(e,t){let o=tt.join(e,".env.example");G.existsSync(o)?G.appendFileSync(o,`
1826
- `+t):G.writeFileSync(o,t)}function vs(e){switch(e){case"stripe":return`# Stripe
1839
+ `}async function eo(e,t,o="global"){let n=Zn(t);if(!n||n.id==="none")return;let r=O.join(e,"apps","web");if(!He.existsSync(r))return;let s=n.id;try{switch(s){case"sentry":Ns(r),ct(e,xs());return;case"datadog":ks(r),ct(e,Ts());return;case"bugsnag":Os(r),ct(e,Us());return;case"aliyun-arms":Ls(r),ct(e,Ms());return;case"tingyun":Ds(r),ct(e,Fs());return;default:return}}catch(a){throw console.error(`Failed to apply monitoring selection "${t}":`,a),new Error(`Monitoring scaffold for "${t}" failed \u2014 see stderr for details.`)}}var wt=[{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 to(e){return wt.find(t=>t.id===e)}var Fc=wt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function no(e,t,o="global"){let n=to(t);if(!n)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${wt.map(r=>r.id).join(", ")}`);if(n.id==="none"){B(e,"notifications");return}n.envVars.length>0&&G(e,{category:"Notifications",name:n.name,envVars:n.envVars,docs:n.docs}),H(e,"NOTIFICATIONS_PROVIDER",n.id)}import $t from"fs";import js from"path";async function oo(e,t){let o=js.join(e,"package.json");if($t.existsSync(o)){let n=$t.readFileSync(o,"utf8"),r=JSON.parse(n);r.name=t,r.version="0.1.0",$t.writeFileSync(o,JSON.stringify(r,null,2)+`
1840
+ `)}}import Z from"fs";import pt from"path";var Vs=["stripe","lemonsqueezy","chinapay","polar"];function ro(e){Z.existsSync(e)&&Z.rmSync(e,{recursive:!0,force:!0})}function Ks(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function Bs(e,t){let o=pt.join(e,".env.example");Z.existsSync(o)?Z.appendFileSync(o,`
1841
+ `+t):Z.writeFileSync(o,t)}function Ys(e){switch(e){case"stripe":return`# Stripe
1827
1842
  STRIPE_SECRET_KEY=
1828
1843
  STRIPE_WEBHOOK_SECRET=
1829
1844
  `;case"lemon":return`# Lemon Squeezy
@@ -1838,14 +1853,14 @@ CHINAPAY_WECHAT_ENABLED=true
1838
1853
  CHINAPAY_APP_ID=
1839
1854
  CHINAPAY_APP_SECRET=
1840
1855
  CHINAPAY_ALIPAY_ENABLED=true
1841
- `}}async function Tn(e,t){let o=tt.join(e,"packages","billing");if(!G.existsSync(o))return;if(t==="none"){xn(o);return}let n=tt.join(o,"src"),r=new Set(Es(t));for(let a of Ss)r.has(a)||xn(tt.join(n,a));let s=tt.join(n,"checkout","types.ts");if(G.existsSync(s)){let a=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",c=G.readFileSync(s,"utf8"),i=c.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${a}";`);i!==c&&G.writeFileSync(s,i)}hs(e,vs(t))}import J from"fs";import Ue from"path";var Un=new Set(["siliconflow","volcengine-ark","bailian","moonshot"]),Ut=/@sailor:([^\s*]+)/;function _s(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=>Un.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 kn(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function On(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function Ln(e,t){let o=e.split(`
1842
- `),n=[],r=e.includes("#"),s=0;for(;s<o.length;){let a=o[s],c=a.match(Ut);if(!c){n.push(a),s++;continue}let{marker:i,keep:d}=_s(c[1],t);if(i==="registry-entries"){n.push(r?On(a):kn(a)),s++;continue}if(d){let m=r?On(a):kn(a);m.trim().length>0&&n.push(m);let E=s+1;for(;E<o.length&&o[E].trim()!==""&&!Ut.test(o[E]);)n.push(o[E]),E++;E<o.length&&o[E].trim()===""&&(n.push(o[E]),E++),s=E}else{let m=s+1;for(;m<o.length&&o[m].trim()!==""&&!Ut.test(o[m]);)m++;m<o.length&&o[m].trim()===""&&m++,s=m}}return Ps(n.join(`
1843
- `),t)}function Ps(e,t){let{providerIds:o,customEndpoint:n}=t,r=new Set;for(let d of o)["openai","anthropic","google","mistral","xai"].includes(d)&&r.add(d),r.add(d.replace(/-/g,"_")),r.add(d);n&&r.add("custom");let s=/createProviderRegistry\(\{([\s\S]*?)\}\)/,a=e.match(s);if(!a)return e;let i=a[1].split(`
1844
- `).filter(d=>{let m=d.trim();if(m===""||m.startsWith("//"))return!0;let E=m.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return E?r.has(E[1]):!0}).join(`
1845
- `);return e.replace(s,`createProviderRegistry({${i}})`)}function Is(e,t){let o=Ue.join(t,"registry.ts.template"),n=J.readFileSync(o,"utf-8");return Ln(n,e)}function Cs(e,t){let o=Ue.join(t,".env.example.template"),n=J.readFileSync(o,"utf-8");return Ln(n,e)}async function Mn(e,t,o){let n=Is(t,o),r=Cs(t,o),s=Ue.join(e,"packages/ai-sdk/src");await J.promises.mkdir(s,{recursive:!0}),await J.promises.writeFile(Ue.join(s,"registry.ts"),n),await J.promises.appendFile(Ue.join(e,".env.example"),`
1846
- `+r);let a={ai:"latest"},{providerIds:c,customEndpoint:i}=t;(c.includes("openai")||i||c.some(m=>Un.has(m)))&&(a["@ai-sdk/openai"]="latest",a["@ai-sdk/openai-compatible"]="latest"),c.includes("anthropic")&&(a["@ai-sdk/anthropic"]="latest"),c.includes("google")&&(a["@ai-sdk/google"]="latest"),c.includes("mistral")&&(a["@ai-sdk/mistral"]="latest"),c.includes("xai")&&(a["@ai-sdk/openai"]="latest");let d=Ue.join(e,"package.json");if(J.existsSync(d)){let m=JSON.parse(await J.promises.readFile(d,"utf-8"));m.dependencies||(m.dependencies={});for(let[E,Pe]of Object.entries(a))m.dependencies[E]=Pe;await J.promises.writeFile(d,JSON.stringify(m,null,2)+`
1847
- `)}}import u from"fs";import h from"path";function Dn(e,t){if(!u.existsSync(e))return;let o=u.readdirSync(e);for(let n of o){let r=h.join(e,n);u.statSync(r).isDirectory()?Dn(r,t):t(r)}}async function jn(e,t){let o=h.join(e,"package.json");if(!u.existsSync(o))return;let n=JSON.parse(u.readFileSync(o,"utf8"));if(t.orm!=="prisma"){let r=h.join(e,"packages","db");if(u.existsSync(r)){let s=h.join(r,"prisma");u.existsSync(s)&&u.rmSync(s,{recursive:!0,force:!0});let a=h.join(r,"package.json");if(u.existsSync(a)){let i=JSON.parse(u.readFileSync(a,"utf8"));i.dependencies&&delete i.dependencies["@prisma/client"],i.devDependencies&&delete i.devDependencies.prisma,u.writeFileSync(a,JSON.stringify(i,null,2)+`
1848
- `)}let c=h.join(r,"src","index.ts");u.existsSync(c)&&u.writeFileSync(c,`
1856
+ `}}async function so(e,t){let o=pt.join(e,"packages","billing");if(!Z.existsSync(o))return;if(t==="none"){ro(o);return}let n=pt.join(o,"src"),r=new Set(Ks(t));for(let a of Vs)r.has(a)||ro(pt.join(n,a));let s=pt.join(n,"checkout","types.ts");if(Z.existsSync(s)){let a=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",c=Z.readFileSync(s,"utf8"),i=c.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${a}";`);i!==c&&Z.writeFileSync(s,i)}Bs(e,Ys(t))}import ae from"fs";import We from"path";var co=new Set(["siliconflow","volcengine-ark","bailian","moonshot"]),qt=/@sailor:([^\s*]+)/;function $s(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=>co.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 io(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function ao(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function po(e,t){let o=e.split(`
1857
+ `),n=[],r=e.includes("#"),s=0;for(;s<o.length;){let a=o[s],c=a.match(qt);if(!c){n.push(a),s++;continue}let{marker:i,keep:d}=$s(c[1],t);if(i==="registry-entries"){n.push(r?ao(a):io(a)),s++;continue}if(d){let u=r?ao(a):io(a);u.trim().length>0&&n.push(u);let S=s+1;for(;S<o.length&&o[S].trim()!==""&&!qt.test(o[S]);)n.push(o[S]),S++;S<o.length&&o[S].trim()===""&&(n.push(o[S]),S++),s=S}else{let u=s+1;for(;u<o.length&&o[u].trim()!==""&&!qt.test(o[u]);)u++;u<o.length&&o[u].trim()===""&&u++,s=u}}return qs(n.join(`
1858
+ `),t)}function qs(e,t){let{providerIds:o,customEndpoint:n}=t,r=new Set;for(let d of o)["openai","anthropic","google","mistral","xai"].includes(d)&&r.add(d),r.add(d.replace(/-/g,"_")),r.add(d);n&&r.add("custom");let s=/createProviderRegistry\(\{([\s\S]*?)\}\)/,a=e.match(s);if(!a)return e;let i=a[1].split(`
1859
+ `).filter(d=>{let u=d.trim();if(u===""||u.startsWith("//"))return!0;let S=u.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return S?r.has(S[1]):!0}).join(`
1860
+ `);return e.replace(s,`createProviderRegistry({${i}})`)}function Gs(e,t){let o=We.join(t,"registry.ts.template"),n=ae.readFileSync(o,"utf-8");return po(n,e)}function Hs(e,t){let o=We.join(t,".env.example.template"),n=ae.readFileSync(o,"utf-8");return po(n,e)}async function lo(e,t,o){let n=Gs(t,o),r=Hs(t,o),s=We.join(e,"packages/agents/src");await ae.promises.mkdir(s,{recursive:!0}),await ae.promises.writeFile(We.join(s,"registry.ts"),n),await ae.promises.appendFile(We.join(e,".env.example"),`
1861
+ `+r);let a={ai:"latest"},{providerIds:c,customEndpoint:i}=t;(c.includes("openai")||i||c.some(u=>co.has(u)))&&(a["@ai-sdk/openai"]="latest",a["@ai-sdk/openai-compatible"]="latest"),c.includes("anthropic")&&(a["@ai-sdk/anthropic"]="latest"),c.includes("google")&&(a["@ai-sdk/google"]="latest"),c.includes("mistral")&&(a["@ai-sdk/mistral"]="latest"),c.includes("xai")&&(a["@ai-sdk/openai"]="latest");let d=We.join(e,"package.json");if(ae.existsSync(d)){let u=JSON.parse(await ae.promises.readFile(d,"utf-8"));u.dependencies||(u.dependencies={});for(let[S,U]of Object.entries(a))u.dependencies[S]=U;await ae.promises.writeFile(d,JSON.stringify(u,null,2)+`
1862
+ `)}}import g from"fs";import v from"path";function uo(e,t){if(!g.existsSync(e))return;let o=g.readdirSync(e);for(let n of o){let r=v.join(e,n);g.statSync(r).isDirectory()?uo(r,t):t(r)}}async function mo(e,t){let o=v.join(e,"package.json");if(!g.existsSync(o))return;let n=JSON.parse(g.readFileSync(o,"utf8"));if(t.orm!=="prisma"){let r=v.join(e,"packages","db");if(g.existsSync(r)){let s=v.join(r,"prisma");g.existsSync(s)&&g.rmSync(s,{recursive:!0,force:!0});let a=v.join(r,"package.json");if(g.existsSync(a)){let i=JSON.parse(g.readFileSync(a,"utf8"));i.dependencies&&delete i.dependencies["@prisma/client"],i.devDependencies&&delete i.devDependencies.prisma,g.writeFileSync(a,JSON.stringify(i,null,2)+`
1863
+ `)}let c=v.join(r,"src","index.ts");g.existsSync(c)&&g.writeFileSync(c,`
1849
1864
  export const prisma = {} as any;
1850
1865
  export const db = {} as any;
1851
1866
  export type PrismaClient = any;
@@ -1891,7 +1906,7 @@ export type UsageAggregate = any;
1891
1906
  export type UsageLedgerEntry = any;
1892
1907
  export type UsageType = any;
1893
1908
  export type UsageLedgerSource = any;
1894
- `)}n.scripts?.postinstall&&(n.scripts.postinstall=n.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let r=h.join(e,"apps");if(u.existsSync(r)){let s=u.readdirSync(r);for(let a of s){let c=h.join(r,a);if(!u.statSync(c).isDirectory())continue;let i=h.join(c,"src","app");if(!u.existsSync(i))continue;["[lang]","[locale]"].forEach(y=>{let l=h.join(i,y);if(u.existsSync(l)){let b=u.readdirSync(l);for(let rt of b)u.renameSync(h.join(l,rt),h.join(i,rt));u.rmdirSync(l)}}),["src/middleware.ts","middleware.ts"].forEach(y=>{let l=h.join(c,y);u.existsSync(l)&&u.rmSync(l)});let d=h.join(c,"src","lib");u.existsSync(d)||u.mkdirSync(d,{recursive:!0});let m=h.join(d,"mock-i18n.ts");u.writeFileSync(m,`
1909
+ `)}n.scripts?.postinstall&&(n.scripts.postinstall=n.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let r=v.join(e,"apps");if(g.existsSync(r)){let s=g.readdirSync(r);for(let a of s){let c=v.join(r,a);if(!g.statSync(c).isDirectory())continue;let i=v.join(c,"src","app");if(!g.existsSync(i))continue;["[lang]","[locale]"].forEach(E=>{let l=v.join(i,E);if(g.existsSync(l)){let N=g.readdirSync(l);for(let ut of N)g.renameSync(v.join(l,ut),v.join(i,ut));g.rmdirSync(l)}}),["src/middleware.ts","middleware.ts"].forEach(E=>{let l=v.join(c,E);g.existsSync(l)&&g.rmSync(l)});let d=v.join(c,"src","lib");g.existsSync(d)||g.mkdirSync(d,{recursive:!0});let u=v.join(d,"mock-i18n.ts");g.writeFileSync(u,`
1895
1910
  import React from 'react';
1896
1911
  export function useTranslations(namespace?: string): any { return (key: string) => key; }
1897
1912
  export function useLocale() { return 'en'; }
@@ -1909,7 +1924,7 @@ export const useRouter = () => ({ push: (...args: any[]) => {}, replace: (...arg
1909
1924
  export default function createMiddleware(...args: any[]) { return (req: any) => req; }
1910
1925
  export function createNavigation(...args: any[]) { return { Link, redirect, usePathname, useRouter, getPathname: () => '/' }; }
1911
1926
  export function defineRouting<T>(config: T): T { return config; }
1912
- `);let Pe=h.join(d,"mock-i18n.d.ts");u.writeFileSync(Pe,`declare module '@/lib/mock-i18n' {
1927
+ `);let U=v.join(d,"mock-i18n.d.ts");g.writeFileSync(U,`declare module '@/lib/mock-i18n' {
1913
1928
  export function useTranslations(namespace?: string): any;
1914
1929
  export function useLocale(): string;
1915
1930
  export const NextIntlClientProvider: React.FC<any>;
@@ -1927,14 +1942,18 @@ export function defineRouting<T>(config: T): T { return config; }
1927
1942
  export function createNavigation(...args: any[]): any;
1928
1943
  export function defineRouting<T>(config: T): T;
1929
1944
  }
1930
- `),u.writeFileSync(h.join(d,"mock-i18n-index.ts"),`
1945
+ `),g.writeFileSync(v.join(d,"mock-i18n-index.ts"),`
1931
1946
  export * from './mock-i18n';
1932
1947
  export { default } from './mock-i18n';
1933
- `);let Ie=h.join(c,"tsconfig.json");if(u.existsSync(Ie))try{let y=u.readFileSync(Ie,"utf8");if(y.includes('"paths": {')){let l=y.replace(/"paths":\s*\{/,`"paths": {
1948
+ `);let F=v.join(c,"tsconfig.json");if(g.existsSync(F))try{let E=g.readFileSync(F,"utf8");if(E.includes('"paths": {')){let l=E.replace(/"paths":\s*\{/,`"paths": {
1934
1949
  "next-intl": ["./src/lib/mock-i18n"],
1935
- "next-intl/*": ["./src/lib/mock-i18n"],`);u.writeFileSync(Ie,l)}}catch{}let Le=h.join(c,"src");u.existsSync(Le)&&Dn(Le,y=>{if(!y.endsWith(".ts")&&!y.endsWith(".tsx"))return;let l=u.readFileSync(y,"utf8"),b=!1;y.endsWith("src/app/layout.tsx")&&l.includes("../providers")&&(l=l.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),b=!0),l=l.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),l=l.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),l.match(/locale\s*:\s*any/)&&(l=l.replace(/locale\s*:\s*any/g,"locale: string"),b=!0),l.match(/lang\s*:\s*any/)&&(l=l.replace(/lang\s*:\s*any/g,"lang: string"),b=!0),l.match(/requestLocale\s*:\s*any/)&&(l=l.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),b=!0),l.match(/\(locale\s*=\s*(.*)\)/)&&(l=l.replace(/\(locale\s*=\s*(.*)\)/g,"() "),b=!0),l.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(l=l.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 })"),b=!0),(y.endsWith("src/app/layout.tsx")||y.endsWith("src/app/sitemap.ts")||y.endsWith("src/app/robots.ts")||y.endsWith("src/components/ui/locale-switcher.tsx")||y.endsWith("src/app/(marketing)/blog/[slug]/page.tsx"))&&(l=l.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),l=l.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),l=l.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),l=l.replace(/\(l\)\s*=>/g,"(l: any) =>"),b=!0),y.endsWith("src/i18n/request.ts")&&(l=l.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),b=!0),(l.match(/locale\s*:/)||l.match(/lang\s*:/))&&(b=!0),b&&u.writeFileSync(y,l)});let Me=h.join(c,"package.json");if(u.existsSync(Me)){let y=JSON.parse(u.readFileSync(Me,"utf8"));y.dependencies&&delete y.dependencies["next-intl"],u.writeFileSync(Me,JSON.stringify(y,null,2)+`
1936
- `)}}}}u.writeFileSync(o,JSON.stringify(n,null,2)+`
1937
- `)}import Z from"fs";import fe from"path";function bs(e){let t=[fe.join(e,"packages","db"),fe.join(e,"apps","web")];for(let o of t){let n=fe.join(o,"prisma","schema.prisma");if(Z.existsSync(n))return{packageDir:o,seedPath:fe.join(o,"prisma","seed.ts"),packageJsonPath:fe.join(o,"package.json")}}return null}function As(e){try{let t=Z.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 Rs(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
1950
+ "next-intl/*": ["./src/lib/mock-i18n"],`);g.writeFileSync(F,l)}}catch{}let ee=v.join(c,"src");g.existsSync(ee)&&uo(ee,E=>{if(!E.endsWith(".ts")&&!E.endsWith(".tsx"))return;let l=g.readFileSync(E,"utf8"),N=!1;E.endsWith("src/app/layout.tsx")&&l.includes("../providers")&&(l=l.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),N=!0),l=l.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),l=l.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),l.match(/locale\s*:\s*any/)&&(l=l.replace(/locale\s*:\s*any/g,"locale: string"),N=!0),l.match(/lang\s*:\s*any/)&&(l=l.replace(/lang\s*:\s*any/g,"lang: string"),N=!0),l.match(/requestLocale\s*:\s*any/)&&(l=l.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),N=!0),l.match(/\(locale\s*=\s*(.*)\)/)&&(l=l.replace(/\(locale\s*=\s*(.*)\)/g,"() "),N=!0),l.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(l=l.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 })"),N=!0),(E.endsWith("src/app/layout.tsx")||E.endsWith("src/app/sitemap.ts")||E.endsWith("src/app/robots.ts")||E.endsWith("src/components/ui/locale-switcher.tsx")||E.endsWith("src/app/(marketing)/blog/[slug]/page.tsx"))&&(l=l.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),l=l.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),l=l.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),l=l.replace(/\(l\)\s*=>/g,"(l: any) =>"),N=!0),E.endsWith("src/i18n/request.ts")&&(l=l.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),N=!0),(l.match(/locale\s*:/)||l.match(/lang\s*:/))&&(N=!0),N&&g.writeFileSync(E,l)});let Xe=v.join(c,"package.json");if(g.existsSync(Xe)){let E=JSON.parse(g.readFileSync(Xe,"utf8"));E.dependencies&&delete E.dependencies["next-intl"],g.writeFileSync(Xe,JSON.stringify(E,null,2)+`
1951
+ `)}}}}g.writeFileSync(o,JSON.stringify(n,null,2)+`
1952
+ `)}import{getSchema as Ws,printSchema as Xs}from"@mrleebo/prisma-ast";var zs=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function Qs(e){return e.type==="comment"&&e.text.trim().startsWith("///")}function Js(e){let t=zs.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 Zs(e,t){for(let o=t-1;o>=0;o--){let n=e[o];if(n.type==="comment"){let r=Js(n.text);if(r)return{annIndex:o,parsed:r};continue}break}return null}function Gt(e,t){let o=Ws(e),n=new Set;for(let c=0;c<o.list.length;c++){if(o.list[c].type!=="model")continue;let d=Zs(o.list,c);if(!d)continue;let u=t[d.parsed.flag];if(u!==void 0&&d.parsed.values.includes(u))n.add(d.annIndex);else{n.add(c);for(let F=c-1;F>=0;F--){let ee=o.list[F];if(ee.type==="comment"&&Qs(ee)){n.add(F);continue}break}let U=o.list[c+1];U&&U.type==="break"&&n.add(c+1)}}let r=o.list.filter((c,i)=>!n.has(i)),s=[];for(let c of r){let i=s[s.length-1];c.type==="break"&&i&&i.type==="break"||s.push(c)}return Xs({type:"schema",list:s})}import ce from"fs";import Ht from"path";var Rt=[{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:"upstash",name:"Upstash Kafka",region:"both",envVars:["UPSTASH_KAFKA_REST_URL","UPSTASH_KAFKA_REST_USERNAME","UPSTASH_KAFKA_REST_PASSWORD"],docs:"https://upstash.com/docs/kafka",description:"Serverless Kafka"},{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 go(e){return Rt.find(t=>t.id===e)}var op=Rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function fo(e){return ce.existsSync(e)?ce.readFileSync(e,"utf-8"):null}function ei(e,t){let o=Ht.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(a=>`${a}=""`),""].join(`
1953
+ `);ce.appendFileSync(o,s)}function ti(e,t,o){let n=Ht.join(e,".env.example"),r=fo(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?ce.writeFileSync(n,r.replace(s,`${t}="${o}"`)):ce.appendFileSync(n,`${t}="${o}"
1954
+ `)}async function yo(e,t,o){let n=Ht.join(e,"packages","queue");if(t==="none"){ce.existsSync(n)&&ce.rmSync(n,{recursive:!0,force:!0});return}let r=go(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${Rt.map(s=>s.id).join(", ")}`);ce.existsSync(n)&&(ei(e,r),ti(e,"QUEUE_PROVIDER",t))}import pe from"fs";import Wt from"path";var Nt=[{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 So(e){return Nt.find(t=>t.id===e)}var pp=Nt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Eo(e){return pe.existsSync(e)?pe.readFileSync(e,"utf-8"):null}function ni(e,t){let o=Wt.join(e,".env.example"),n=Eo(o);if(n===null)return;let r=`# Search: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(a=>`${a}=""`),""].join(`
1955
+ `);pe.appendFileSync(o,s)}function oi(e,t,o){let n=Wt.join(e,".env.example"),r=Eo(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?pe.writeFileSync(n,r.replace(s,`${t}="${o}"`)):pe.appendFileSync(n,`${t}="${o}"
1956
+ `)}async function ho(e,t,o){let n=Wt.join(e,"packages","search");if(t==="none"){pe.existsSync(n)&&pe.rmSync(n,{recursive:!0,force:!0});return}let r=So(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${Nt.map(s=>s.id).join(", ")}`);pe.existsSync(n)&&(ni(e,r),oi(e,"SEARCH_PROVIDER",t))}import le from"fs";import be from"path";function ri(e){let t=[be.join(e,"packages","db"),be.join(e,"apps","web")];for(let o of t){let n=be.join(o,"prisma","schema.prisma");if(le.existsSync(n))return{packageDir:o,seedPath:be.join(o,"prisma","seed.ts"),packageJsonPath:be.join(o,"package.json")}}return null}function si(e){try{let t=le.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 ii(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
1938
1957
  const admin = await prisma.user.create({
1939
1958
  data: {
1940
1959
  clerkId: "user_mock_admin",
@@ -1965,7 +1984,7 @@ export { default } from './mock-i18n';
1965
1984
  console.log("\\u2713 Created admin user:", admin.email);
1966
1985
  } catch (err) {
1967
1986
  console.warn("\\u26A0 Admin user creation skipped:", (err as Error).message);
1968
- }`}function ws(e,t){let o=t.has("Tenant"),n=t.has("User"),r=t.has("Project"),s=Rs(e,n),a=o?` let tenants: Array<{ id: string; name: string }> = [];
1987
+ }`}function ai(e,t){let o=t.has("Tenant"),n=t.has("User"),r=t.has("Project"),s=ii(e,n),a=o?` let tenants: Array<{ id: string; name: string }> = [];
1969
1988
  try {
1970
1989
  tenants = await Promise.all([
1971
1990
  prisma.tenant.create({
@@ -2034,12 +2053,12 @@ main()
2034
2053
  .finally(async () => {
2035
2054
  await prisma.$disconnect();
2036
2055
  });
2037
- `}function Ns(e){if(Z.existsSync(e))try{let t=Z.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 a={...o,scripts:n,prisma:s};Z.writeFileSync(e,JSON.stringify(a,null,2)+`
2038
- `)}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 Fn(e,t){let o=bs(e);if(o)try{let n=fe.join(o.packageDir,"prisma","schema.prisma"),r=As(n),s=ws(t,r),a=fe.dirname(o.seedPath);Z.existsSync(a)||Z.mkdirSync(a,{recursive:!0}),Z.writeFileSync(o.seedPath,s),Ns(o.packageJsonPath)}catch(n){let r=n instanceof Error?n.message:String(n);throw console.error(`[create-sailor] Failed to generate seed data: ${r}`),new Error(`Unable to write prisma/seed.ts: ${r}`)}}import ee from"fs";import ye from"path";var ft=[{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:""}],qa=ft.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Vn(e){return ft.find(t=>t.id===e)}var xs="@nebutra/sms",Ts={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 Lt(e,t){ee.mkdirSync(ye.dirname(e),{recursive:!0}),ee.writeFileSync(e,t)}function ks(e,t){let o=ye.join(e,".env.example");ee.existsSync(o)?ee.appendFileSync(o,`
2039
- `+t):ee.writeFileSync(o,t)}function Os(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2056
+ `}function ci(e){if(le.existsSync(e))try{let t=le.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 a={...o,scripts:n,prisma:s};le.writeFileSync(e,JSON.stringify(a,null,2)+`
2057
+ `)}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 vo(e,t){let o=ri(e);if(o)try{let n=be.join(o.packageDir,"prisma","schema.prisma"),r=si(n),s=ai(t,r),a=be.dirname(o.seedPath);le.existsSync(a)||le.mkdirSync(a,{recursive:!0}),le.writeFileSync(o.seedPath,s),ci(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 de from"fs";import Ie from"path";var xt=[{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:""}],Ep=xt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function _o(e){return xt.find(t=>t.id===e)}var pi="@nebutra/sms",li={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 Xt(e,t){de.mkdirSync(Ie.dirname(e),{recursive:!0}),de.writeFileSync(e,t)}function di(e,t){let o=Ie.join(e,".env.example");de.existsSync(o)?de.appendFileSync(o,`
2058
+ `+t):de.writeFileSync(o,t)}function ui(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2040
2059
  `);return`${t}
2041
2060
  ${o}
2042
- `}var Us=`/**
2061
+ `}var mi=`/**
2043
2062
  * Inputs for the \`sendSms\` wrapper. Keep this surface portable across
2044
2063
  * providers \u2014 provider-specific options belong in the wrapper itself.
2045
2064
  */
@@ -2059,7 +2078,7 @@ export interface SendSmsResult {
2059
2078
  provider: string;
2060
2079
  raw?: unknown;
2061
2080
  }
2062
- `;function Ls(){return`import twilio from "twilio";
2081
+ `;function gi(){return`import twilio from "twilio";
2063
2082
  import type { SendSmsInput, SendSmsResult } from "./types.js";
2064
2083
 
2065
2084
  let client: ReturnType<typeof twilio> | null = null;
@@ -2094,7 +2113,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2094
2113
  }
2095
2114
 
2096
2115
  export type { SendSmsInput, SendSmsResult } from "./types.js";
2097
- `}function Ms(){return`import messagebird from "messagebird";
2116
+ `}function fi(){return`import messagebird from "messagebird";
2098
2117
  import type { SendSmsInput, SendSmsResult } from "./types.js";
2099
2118
 
2100
2119
  let client: ReturnType<typeof messagebird> | null = null;
@@ -2132,7 +2151,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2132
2151
  }
2133
2152
 
2134
2153
  export type { SendSmsInput, SendSmsResult } from "./types.js";
2135
- `}function Ds(){return`import plivo from "plivo";
2154
+ `}function yi(){return`import plivo from "plivo";
2136
2155
  import type { SendSmsInput, SendSmsResult } from "./types.js";
2137
2156
 
2138
2157
  let client: InstanceType<typeof plivo.Client> | null = null;
@@ -2171,7 +2190,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2171
2190
  }
2172
2191
 
2173
2192
  export type { SendSmsInput, SendSmsResult } from "./types.js";
2174
- `}function js(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2193
+ `}function Si(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2175
2194
  import * as $OpenApi from "@alicloud/openapi-client";
2176
2195
  import type { SendSmsInput, SendSmsResult } from "./types.js";
2177
2196
 
@@ -2220,7 +2239,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2220
2239
  }
2221
2240
 
2222
2241
  export type { SendSmsInput, SendSmsResult } from "./types.js";
2223
- `}function Fs(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2242
+ `}function Ei(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2224
2243
  import type { SendSmsInput, SendSmsResult } from "./types.js";
2225
2244
 
2226
2245
  const SmsClient = tencentcloud.sms.v20210111.Client;
@@ -2285,7 +2304,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2285
2304
  }
2286
2305
 
2287
2306
  export type { SendSmsInput, SendSmsResult } from "./types.js";
2288
- `}function Vs(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2307
+ `}function hi(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2289
2308
  import Yunpian from "yunpian-nodejs-sdk";
2290
2309
  import type { SendSmsInput, SendSmsResult } from "./types.js";
2291
2310
 
@@ -2337,13 +2356,13 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2337
2356
  }
2338
2357
 
2339
2358
  export type { SendSmsInput, SendSmsResult } from "./types.js";
2340
- `}function Ks(e){switch(e){case"twilio":return Ls();case"messagebird":return Ms();case"plivo":return Ds();case"aliyun-sms":return js();case"tencent-sms":return Fs();case"yunpian":return Vs();case"none":return`export {};
2341
- `}}function Ys(e){let t={};for(let n of e.pkgs??[]){let r=Ts[n];r&&(t[n]=r)}let o={name:xs,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)+`
2342
- `}async function Kn(e,t,o="global"){if(t==="none")return;let n=Vn(t);if(!n)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${ft.map(a=>a.id).join(", ")}`);let r=ye.join(e,"packages","sms");if(!ee.existsSync(r))return;let s=ye.join(r,"src");ee.existsSync(s)&&ee.rmSync(s,{recursive:!0,force:!0});try{Lt(ye.join(r,"package.json"),Ys(n)),Lt(ye.join(s,"types.ts"),Us),Lt(ye.join(s,"index.ts"),Ks(n.id)),ks(e,Os(n))}catch(a){throw console.error(`Failed to apply SMS selection "${t}":`,a),new Error(`SMS scaffold for "${t}" failed \u2014 see stderr for details.`)}}import Ee from"fs";import Se from"path";var yt=[{id:"r2",name:"Cloudflare R2",region:"global",envVars:["R2_ACCOUNT_ID","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY","R2_BUCKET"],docs:"https://developers.cloudflare.com/r2/api/s3/api/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"s3",name:"AWS S3",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_S3_REGION","S3_BUCKET"],docs:"https://docs.aws.amazon.com/s3/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"supabase-storage",name:"Supabase Storage",region:"global",envVars:["SUPABASE_URL","SUPABASE_SERVICE_ROLE_KEY","SUPABASE_BUCKET"],docs:"https://supabase.com/docs/guides/storage",pkg:"@supabase/supabase-js",pkgVersion:"^2.45.4"},{id:"aliyun-oss",name:"\u963F\u91CC\u4E91 OSS",region:"cn",envVars:["ALIYUN_OSS_ACCESS_KEY","ALIYUN_OSS_ACCESS_SECRET","ALIYUN_OSS_REGION","ALIYUN_OSS_BUCKET"],docs:"https://help.aliyun.com/product/31815.html",pkg:"ali-oss",pkgVersion:"^6.21.0"},{id:"tencent-cos",name:"\u817E\u8BAF\u4E91 COS",region:"cn",envVars:["TENCENT_COS_SECRET_ID","TENCENT_COS_SECRET_KEY","TENCENT_COS_BUCKET","TENCENT_COS_REGION"],docs:"https://cloud.tencent.com/document/product/436",pkg:"cos-nodejs-sdk-v5",pkgVersion:"^2.13.7"},{id:"qiniu",name:"\u4E03\u725B\u4E91 Kodo",region:"cn",envVars:["QINIU_ACCESS_KEY","QINIU_SECRET_KEY","QINIU_BUCKET","QINIU_DOMAIN"],docs:"https://developer.qiniu.com/kodo",pkg:"qiniu",pkgVersion:"^7.14.0"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function Yn(e){return yt.find(t=>t.id===e)}var Qa=yt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var he="@nebutra/storage";function Mt(e,t){Ee.mkdirSync(Se.dirname(e),{recursive:!0}),Ee.writeFileSync(e,t)}function Bs(e,t){let o=Se.join(e,".env.example");Ee.existsSync(o)?Ee.appendFileSync(o,`
2343
- `+t):Ee.writeFileSync(o,t)}function $s(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2359
+ `}function vi(e){switch(e){case"twilio":return gi();case"messagebird":return fi();case"plivo":return yi();case"aliyun-sms":return Si();case"tencent-sms":return Ei();case"yunpian":return hi();case"none":return`export {};
2360
+ `}}function _i(e){let t={};for(let n of e.pkgs??[]){let r=li[n];r&&(t[n]=r)}let o={name:pi,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)+`
2361
+ `}async function Po(e,t,o="global"){if(t==="none")return;let n=_o(t);if(!n)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${xt.map(a=>a.id).join(", ")}`);let r=Ie.join(e,"packages","sms");if(!de.existsSync(r))return;let s=Ie.join(r,"src");de.existsSync(s)&&de.rmSync(s,{recursive:!0,force:!0});try{Xt(Ie.join(r,"package.json"),_i(n)),Xt(Ie.join(s,"types.ts"),mi),Xt(Ie.join(s,"index.ts"),vi(n.id)),di(e,ui(n))}catch(a){throw console.error(`Failed to apply SMS selection "${t}":`,a),new Error(`SMS scaffold for "${t}" failed \u2014 see stderr for details.`)}}import Ae from"fs";import Ce from"path";var kt=[{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 bo(e){return kt.find(t=>t.id===e)}var Ip=kt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var we="@nebutra/storage";function zt(e,t){Ae.mkdirSync(Ce.dirname(e),{recursive:!0}),Ae.writeFileSync(e,t)}function Pi(e,t){let o=Ce.join(e,".env.example");Ae.existsSync(o)?Ae.appendFileSync(o,`
2362
+ `+t):Ae.writeFileSync(o,t)}function bi(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2344
2363
  `);return`${t}
2345
2364
  ${o}
2346
- `}var qs=`/**
2365
+ `}var Ii=`/**
2347
2366
  * Inputs for the \`uploadFile\` wrapper. Keep this surface portable across
2348
2367
  * providers \u2014 provider-specific options belong in the wrapper itself.
2349
2368
  */
@@ -2369,8 +2388,8 @@ export interface SignedUrlOptions {
2369
2388
  operation?: "get" | "put";
2370
2389
  contentType?: string;
2371
2390
  }
2372
- `;function Gs(){return`/**
2373
- * @${he.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
2391
+ `;function Ci(){return`/**
2392
+ * @${we.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
2374
2393
  *
2375
2394
  * Docs: https://developers.cloudflare.com/r2/api/s3/api/
2376
2395
  */
@@ -2433,8 +2452,8 @@ export async function getSignedUrl(
2433
2452
  }
2434
2453
 
2435
2454
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2436
- `}function Hs(){return`/**
2437
- * @${he.slice(1)} \u2014 AWS S3 wrapper.
2455
+ `}function Ai(){return`/**
2456
+ * @${we.slice(1)} \u2014 AWS S3 wrapper.
2438
2457
  *
2439
2458
  * Docs: https://docs.aws.amazon.com/s3/
2440
2459
  */
@@ -2498,8 +2517,8 @@ export async function getSignedUrl(
2498
2517
  }
2499
2518
 
2500
2519
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2501
- `}function Ws(){return`/**
2502
- * @${he.slice(1)} \u2014 Supabase Storage wrapper.
2520
+ `}function wi(){return`/**
2521
+ * @${we.slice(1)} \u2014 Supabase Storage wrapper.
2503
2522
  *
2504
2523
  * Docs: https://supabase.com/docs/guides/storage
2505
2524
  */
@@ -2561,8 +2580,8 @@ export async function getSignedUrl(
2561
2580
  }
2562
2581
 
2563
2582
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2564
- `}function Xs(){return`/**
2565
- * @${he.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2583
+ `}function Ri(){return`/**
2584
+ * @${we.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2566
2585
  *
2567
2586
  * Docs: https://help.aliyun.com/product/31815.html
2568
2587
  */
@@ -2608,8 +2627,8 @@ export async function getSignedUrl(
2608
2627
  }
2609
2628
 
2610
2629
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2611
- `}function zs(){return`/**
2612
- * @${he.slice(1)} \u2014 \u817E\u8BAF\u4E91 COS wrapper via cos-nodejs-sdk-v5.
2630
+ `}function Ni(){return`/**
2631
+ * @${we.slice(1)} \u2014 \u817E\u8BAF\u4E91 COS wrapper via cos-nodejs-sdk-v5.
2613
2632
  *
2614
2633
  * Docs: https://cloud.tencent.com/document/product/436
2615
2634
  */
@@ -2663,8 +2682,8 @@ export async function getSignedUrl(
2663
2682
  }
2664
2683
 
2665
2684
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2666
- `}function Qs(){return`/**
2667
- * @${he.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2685
+ `}function xi(){return`/**
2686
+ * @${we.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2668
2687
  *
2669
2688
  * Docs: https://developer.qiniu.com/kodo
2670
2689
  */
@@ -2731,21 +2750,9 @@ export async function getSignedUrl(
2731
2750
  }
2732
2751
 
2733
2752
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2734
- `}function Js(e){switch(e){case"r2":return Gs();case"s3":return Hs();case"supabase-storage":return Ws();case"aliyun-oss":return Xs();case"tencent-cos":return zs();case"qiniu":return Qs();case"none":return`export {};
2735
- `}}function Zs(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:he,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)+`
2736
- `}async function Bn(e,t,o){if(t==="none")return;let n=Yn(t);if(!n)throw new Error(`Unknown storage provider "${t}". Valid ids: ${yt.map(a=>a.id).join(", ")}`);let r=Se.join(e,"packages","storage"),s=Se.join(r,"src");Ee.existsSync(s)&&Ee.rmSync(s,{recursive:!0,force:!0}),Mt(Se.join(r,"package.json"),Zs(n)),Mt(Se.join(s,"types.ts"),qs),Mt(Se.join(s,"index.ts"),Js(n.id)),Bs(e,$s(n))}import te from"fs";import Dt from"path";var St=[{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:"upstash",name:"Upstash Kafka",region:"both",envVars:["UPSTASH_KAFKA_REST_URL","UPSTASH_KAFKA_REST_USERNAME","UPSTASH_KAFKA_REST_PASSWORD"],docs:"https://upstash.com/docs/kafka",description:"Serverless Kafka"},{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 $n(e){return St.find(t=>t.id===e)}var oc=St.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function qn(e){return te.existsSync(e)?te.readFileSync(e,"utf-8"):null}function ei(e,t){let o=Dt.join(e,".env.example"),n=qn(o);if(n===null)return;let r=`# Queue: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(a=>`${a}=""`),""].join(`
2737
- `);te.appendFileSync(o,s)}function ti(e,t,o){let n=Dt.join(e,".env.example"),r=qn(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?te.writeFileSync(n,r.replace(s,`${t}="${o}"`)):te.appendFileSync(n,`${t}="${o}"
2738
- `)}async function Gn(e,t,o){let n=Dt.join(e,"packages","queue");if(t==="none"){te.existsSync(n)&&te.rmSync(n,{recursive:!0,force:!0});return}let r=$n(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${St.map(s=>s.id).join(", ")}`);te.existsSync(n)&&(ei(e,r),ti(e,"QUEUE_PROVIDER",t))}import ne from"fs";import jt from"path";var Et=[{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 Hn(e){return Et.find(t=>t.id===e)}var pc=Et.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Wn(e){return ne.existsSync(e)?ne.readFileSync(e,"utf-8"):null}function ni(e,t){let o=jt.join(e,".env.example"),n=Wn(o);if(n===null)return;let r=`# Search: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(a=>`${a}=""`),""].join(`
2739
- `);ne.appendFileSync(o,s)}function oi(e,t,o){let n=jt.join(e,".env.example"),r=Wn(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?ne.writeFileSync(n,r.replace(s,`${t}="${o}"`)):ne.appendFileSync(n,`${t}="${o}"
2740
- `)}async function Xn(e,t,o){let n=jt.join(e,"packages","search");if(t==="none"){ne.existsSync(n)&&ne.rmSync(n,{recursive:!0,force:!0});return}let r=Hn(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${Et.map(s=>s.id).join(", ")}`);ne.existsSync(n)&&(ni(e,r),oi(e,"SEARCH_PROVIDER",t))}import oe from"fs";import Ft from"path";var ht=[{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 zn(e){return ht.find(t=>t.id===e)}var fc=ht.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Qn(e){return oe.existsSync(e)?oe.readFileSync(e,"utf-8"):null}function ri(e,t){let o=Ft.join(e,".env.example"),n=Qn(o);if(n===null)return;let r=`# Cache: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(a=>`${a}=""`),""].join(`
2741
- `);oe.appendFileSync(o,s)}function si(e,t,o){let n=Ft.join(e,".env.example"),r=Qn(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?oe.writeFileSync(n,r.replace(s,`${t}="${o}"`)):oe.appendFileSync(n,`${t}="${o}"
2742
- `)}async function Jn(e,t,o){let n=Ft.join(e,"packages","cache");if(t==="none"){oe.existsSync(n)&&oe.rmSync(n,{recursive:!0,force:!0});return}let r=zn(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${ht.map(s=>s.id).join(", ")}`);oe.existsSync(n)&&(ri(e,r),si(e,"CACHE_PROVIDER",t))}import H from"fs";import Vt from"path";function B(e,t){let o=Vt.join(e,".env.example");if(!H.existsSync(o)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(H.readFileSync(o,"utf-8").includes(r))return;let c=["","# =============================================",r,t.docs?`# Docs: ${t.docs}`:null,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].filter(i=>i!==null).join(`
2743
- `);H.appendFileSync(o,c)}function $(e,t,o){let n=Vt.join(e,".env.example");if(!H.existsSync(n))return;let r=H.readFileSync(n,"utf-8"),s=`${t}="${o}"`,a=new RegExp(`^${t}=.*$`,"m");if(a.test(r)){H.writeFileSync(n,r.replace(a,s));return}let c=r.endsWith(`
2744
- `)?"":`
2745
- `;H.appendFileSync(n,`${c}${s}
2746
- `)}function U(e,t){let o=Vt.join(e,"packages",t);H.existsSync(o)&&H.rmSync(o,{recursive:!0,force:!0})}var vt=[{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 Zn(e){return vt.find(t=>t.id===e)}var Cc=vt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function eo(e,t,o="global"){let n=Zn(t);if(!n)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${vt.map(r=>r.id).join(", ")}`);if(n.id==="none"){U(e,"notifications");return}n.envVars.length>0&&B(e,{category:"Notifications",name:n.name,envVars:n.envVars,docs:n.docs}),$(e,"NOTIFICATIONS_PROVIDER",n.id)}var _t=[{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 to(e){return _t.find(t=>t.id===e)}var Nc=_t.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function no(e,t,o="global"){let n=to(t);if(!n)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${_t.map(r=>r.id).join(", ")}`);if(n.id==="none"){U(e,"webhooks");return}n.envVars.length>0&&B(e,{category:"Webhooks",name:n.name,envVars:n.envVars,docs:n.docs}),$(e,"WEBHOOKS_PROVIDER",n.id)}import It from"fs";import ii from"path";var Pt=[{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 oo(e){return Pt.find(t=>t.id===e)}var Uc=Pt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function ro(e,t,o="global"){let n=oo(t);if(!n)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${Pt.map(s=>s.id).join(", ")}`);let r=ii.join(e,"apps","studio");if(n.id==="none"){U(e,"sanity"),It.existsSync(r)&&It.rmSync(r,{recursive:!0,force:!0});return}n.id!=="sanity"&&(U(e,"sanity"),It.existsSync(r)&&It.rmSync(r,{recursive:!0,force:!0})),n.envVars.length>0&&B(e,{category:"CMS",name:n.name,envVars:n.envVars,docs:n.docs}),$(e,"CMS_PROVIDER",n.id)}var Ct=[{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 so(e){return Ct.find(t=>t.id===e)}var Kc=Ct.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function io(e,t,o="global"){let n=so(t);if(!n)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${Ct.map(r=>r.id).join(", ")}`);if(n.id==="none"){U(e,"feature-flags");return}n.envVars.length>0&&B(e,{category:"Feature Flags",name:n.name,envVars:n.envVars,docs:n.docs}),$(e,"FEATURE_FLAGS_PROVIDER",n.id)}var bt=[{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 ao(e){return bt.find(t=>t.id===e)}var Gc=bt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function co(e,t,o="global"){let n=ao(t);if(!n)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${bt.map(r=>r.id).join(", ")}`);if(n.id==="none"){U(e,"captcha");return}n.envVars.length>0&&B(e,{category:"Captcha",name:n.name,envVars:n.envVars,docs:n.docs}),$(e,"CAPTCHA_PROVIDER",n.id)}import ve from"fs";import Kt from"path";async function po(e,t){let o=Kt.join(e,"packages","mcp");if(t==="off"){ve.existsSync(o)&&ve.rmSync(o,{recursive:!0,force:!0});let r=Kt.join(e,"packages","cli","src","commands","mcp-server.ts");ve.existsSync(r)&&ve.rmSync(r,{force:!0});return}let n=Kt.join(e,".env.example");if(ve.existsSync(n)){let r=ve.readFileSync(n,"utf-8"),s="# MCP Server (Agent-friendly API)";if(!r.includes(s)){let a=["","# =============================================",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(`
2747
- `);ve.appendFileSync(n,a)}}}import nt from"fs";import lo from"path";async function uo(e,t,o){let n=lo.join(e,"packages","metering"),r;if(t==="auto"?r=o!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){nt.existsSync(n)&&nt.rmSync(n,{recursive:!0,force:!0});return}let s=lo.join(e,".env.example");if(!nt.existsSync(s))return;let a=nt.readFileSync(s,"utf-8"),c="# Metering (usage-based billing)";if(!a.includes(c)){let i=["","# =============================================",c,"# Docs: see packages/metering/README.md","# =============================================","# ClickHouse-based metering pipeline for consumption billing.",'CLICKHOUSE_URL=""','CLICKHOUSE_USER="default"','CLICKHOUSE_PASSWORD=""','CLICKHOUSE_DATABASE="metering"',""].join(`
2748
- `);nt.appendFileSync(s,i)}}import _e from"fs";import ot from"path";function ai(e){return`import Link from "next/link";
2753
+ `}function ki(e){switch(e){case"r2":return Ci();case"s3":return Ai();case"supabase-storage":return wi();case"aliyun-oss":return Ri();case"tencent-cos":return Ni();case"qiniu":return xi();case"none":return`export {};
2754
+ `}}function Ti(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:we,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)+`
2755
+ `}async function Io(e,t,o){if(t==="none")return;let n=bo(t);if(!n)throw new Error(`Unknown storage provider "${t}". Valid ids: ${kt.map(a=>a.id).join(", ")}`);let r=Ce.join(e,"packages","storage"),s=Ce.join(r,"src");Ae.existsSync(s)&&Ae.rmSync(s,{recursive:!0,force:!0}),zt(Ce.join(r,"package.json"),Ti(n)),zt(Ce.join(s,"types.ts"),Ii),zt(Ce.join(s,"index.ts"),ki(n.id)),Pi(e,bi(n))}var Tt=[{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 Co(e){return Tt.find(t=>t.id===e)}var xp=Tt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Ao(e,t,o="global"){let n=Co(t);if(!n)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Tt.map(r=>r.id).join(", ")}`);if(n.id==="none"){B(e,"webhooks");return}n.envVars.length>0&&G(e,{category:"Webhooks",name:n.name,envVars:n.envVars,docs:n.docs}),H(e,"WEBHOOKS_PROVIDER",n.id)}import Re from"fs";import lt from"path";function Oi(e){return`import Link from "next/link";
2749
2756
 
2750
2757
  export default function WelcomePage() {
2751
2758
  const projectName = ${JSON.stringify(e)};
@@ -2785,9 +2792,9 @@ export default function WelcomePage() {
2785
2792
  />
2786
2793
  <Step
2787
2794
  number={4}
2788
- title="Customize your brand"
2789
- description="Colors, domain, logo, SEO \u2014 all in one file"
2790
- command="pnpm sailor brand init"
2795
+ title="Initialize brand config"
2796
+ description="Generate brand.config.ts, then run pnpm brand:apply after edits"
2797
+ command="pnpm brand:init"
2791
2798
  />
2792
2799
  </ol>
2793
2800
  </section>
@@ -2854,7 +2861,7 @@ function Step({
2854
2861
  </li>
2855
2862
  );
2856
2863
  }
2857
- `}function ci(e,t){return`# Next steps \u2014 ${e}
2864
+ `}function Ui(e,t){return`# Next steps \u2014 ${e}
2858
2865
 
2859
2866
  Region: ${t}
2860
2867
 
@@ -2873,9 +2880,10 @@ Your AI-native SaaS scaffold is ready. Complete these four steps to go from temp
2873
2880
  pnpm db:seed
2874
2881
  \`\`\`
2875
2882
 
2876
- 4. **Customize your brand** \u2014 colors, domain, logo, SEO \u2014 all in one file
2883
+ 4. **Initialize your brand config** \u2014 generate \`brand.config.ts\`, then apply it after edits
2877
2884
  \`\`\`bash
2878
- pnpm sailor brand init
2885
+ pnpm brand:init
2886
+ pnpm brand:apply
2879
2887
  \`\`\`
2880
2888
 
2881
2889
  After setup, delete the welcome route at \`apps/web/src/app/[locale]/welcome/\`.
@@ -2885,23 +2893,26 @@ After setup, delete the welcome route at \`apps/web/src/app/[locale]/welcome/\`.
2885
2893
  - [Documentation](/docs)
2886
2894
  - [GitHub](https://github.com/nebutra/nebutra-sailor)
2887
2895
  - [Get free license (Individual/OPC)](https://nebutra.com/get-license)
2888
- `}async function mo(e,t){let{projectName:o,region:n}=t;try{let r=ot.join(e,".sailor");_e.existsSync(r)||_e.mkdirSync(r,{recursive:!0}),_e.writeFileSync(ot.join(r,"next-steps.md"),ci(o,n))}catch(r){let s=r instanceof Error?r.message:String(r);console.warn(`[create-sailor] Failed to write .sailor/next-steps.md: ${s}`)}try{let r=ot.join(e,"apps","web");if(!_e.existsSync(r))return;let s=ot.join(r,"src","app","[locale]","welcome");_e.existsSync(s)||_e.mkdirSync(s,{recursive:!0}),_e.writeFileSync(ot.join(s,"page.tsx"),ai(o))}catch(r){let s=r instanceof Error?r.message:String(r);console.warn(`[create-sailor] Failed to write welcome page: ${s}`)}}var fo="create-sailor";function p(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2889
- `)}function di(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function yo(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 So(e){return e==="drizzle"?"drizzle":e==="none"?"none":"prisma"}function Eo(e){return e==="lemon"||e==="lemonsqueezy"?"lemonsqueezy":e==="none"?"none":"stripe"}function ho(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 vo(e){if(!e)return"clerk";let t=e.toLowerCase();return t==="betterauth"||t==="better-auth"?"betterauth":t==="none"?"none":"clerk"}function _o(e){if(!e)return["openai"];let t=e.split(",").map(o=>o.trim().toLowerCase());return t.includes("none")?[]:t}var Po={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function Io(e,t){if(!e)return"fumadocs";let o=e.toLowerCase();if(o==="fumadocs"||o==="none")return o;if(o in Po){let n=Po[o];return t?p(!0,{event:"notice",kind:"docs-fallback",requested:o,effective:"fumadocs"}):process.stdout.write(x.yellow(`\u26A0 ${n} support is coming in v1.2. Falling back to fumadocs.
2890
- `)+x.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
2891
- `)),"fumadocs"}return"fumadocs"}function Co(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 bo(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function ui(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"}}function Ao(e){return e==="cn"?"wechat":"stripe"}async function mi(){let e=new pi;e.name(fo).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(se,"-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 | drizzle | none").option("--db <id>","postgres | mysql | sqlite | none").option("--auth <id>","clerk | betterauth | 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 <ids>","comma-separated provider ids").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 | 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 | upstash | 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("--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&&(Ht(),process.exit(0));let n=!!t.json,r=!!t.dryRun,s=!!t.yes,a=s||!process.stdin.isTTY;n||qt(),p(n,{event:"start",version:se});let c=o??(s?"./my-saas-app":void 0),i;if(c)i=c;else if(a)i="./my-saas-app";else{let g=await P.group({name:()=>P.text({message:"Where should we create your project?",placeholder:"./my-saas-app",defaultValue:"./my-saas-app",validate:S=>{if(S.length===0)return"Please enter a path."}})},{onCancel:()=>{process.stdout.write(x.red(`\u2718 Cancelled
2892
- `)),process.exit(130)}});i=String(g.name)}let d=Yt.basename(Yt.resolve(i)),m=t.pm??di(),E=!!t.region,Pe=!!t.auth,Ie=!!t.payment,Le=!!t.ai,Me=!!t.email,y=!!t.storage,l=!!t.monitoring,b=!!t.analytics,rt=!!t.sms,Bt=t.i18n!==void 0,f,De,q,je,W,L,M=on(t.socialLogin),re,Ce,X,T,st;if(a){f=bo(t.region),De=So(t.orm),q=yo(t.db);let g=Ie?t.payment:Ao(f);je=Eo(g),W=ho(g),L=vo(t.auth),re=_o(t.ai),X=Co(t.deploy),T=Io(t.docs,n),st=Bt?!!t.i18n:!0}else{let g={};if(E||(g.region=()=>P.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"})),Pe||(g.auth=()=>P.select({message:"Auth provider?",options:[{value:"clerk",label:"Clerk"},{value:"betterauth",label:"Better Auth"},{value:"none",label:"None"}],initialValue:"clerk"})),!Le){let pt=Array.from(new Set(ut.map(v=>v.category)));g.aiCategories=()=>P.multiselect({message:"Which AI Provider categories do you want to explore? (Select multiple)",options:pt.map(v=>({value:v,label:v})),initialValues:["\u76F4\u63A5\u5B9E\u9A8C\u5BA4","\u7EDF\u4E00\u7F51\u5173"]}),g.aiProviders=({results:v})=>{let D=v.aiCategories||[],lt=ut.filter(We=>D.includes(We.category)).map(We=>({value:We.id,label:`[${We.category}] ${We.name}`}));return lt.push({value:"custom",label:"[\u81EA\u5B9A\u4E49] Custom OpenAI-compatible endpoint"}),P.multiselect({message:"Select AI Providers (Space to select, Enter to submit)",options:lt,initialValues:["openai","anthropic"],required:!1})},g.enableCustom=({results:v})=>v.aiProviders?.includes("custom")?P.confirm({message:"Configure custom OpenAI-compatible endpoint?",initialValue:!0}):Promise.resolve(!1),g.customAiName=({results:v})=>v.enableCustom?P.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),g.customAiBaseUrl=({results:v})=>v.enableCustom?P.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:D=>{if(D.length===0)return"Base URL is required."}}):Promise.resolve(void 0),g.customAiApiKeyEnv=({results:v})=>v.enableCustom?P.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0)}let S=Object.keys(g).length>0?await P.group(g,{onCancel:()=>{process.stdout.write(x.red(`\u2718 Cancelled
2893
- `)),process.exit(130)}}):{};f=bo(E?t.region:S.region),De=So(t.orm),q=yo(t.db);let k=Ie?t.payment:Ao(f);je=Eo(k),W=ho(k),L=vo(Pe?t.auth:S.auth),re=Le?_o(t.ai):S.aiProviders?.filter(pt=>pt!=="custom")??[],S.enableCustom&&(Ce={name:S.customAiName,baseURL:S.customAiBaseUrl,apiKeyEnvName:S.customAiApiKeyEnv}),X=Co(t.deploy),T=Io(t.docs,n),st=Bt?!!t.i18n:!0}let C=ui(f),be=Me?t.email:C.email,Ae=y?t.storage:C.storage,Re=l?t.monitoring:C.monitoring,we=b?t.analytics:C.analytics,Ne=rt?t.sms:C.sms,Fe=t.queue??C.queue,Ve=t.search??C.search,Ke=t.cache??C.cache,Ye=t.notifications??C.notifications,Be=t.webhooks??C.webhooks,$e=t.cms??C.cms,qe=t.featureFlags??C.featureFlags,Ge=t.captcha??C.captcha,it=t.mcp??C.mcp,He=t.metering??C.metering,at={region:f,orm:De,database:q,payment:je,aiProviders:re,customAiEndpoint:Ce,deployTarget:X,docs:T,i18n:st,email:be,storage:Ae,monitoring:Re,analytics:we,sms:Ne,queue:Fe,search:Ve,cache:Ke,notifications:Ye,webhooks:Be,cms:$e,featureFlags:qe,captcha:Ge,mcp:it,metering:He},ct=[["Project name",d],["Region",f],["Auth",L],["Social login",M.length>0?M.map(g=>Xe.find(S=>S.id===g)?.name??g).join(", "):"none"],["ORM",De],["Database",q],["Payment",W],["AI",Array.isArray(re)?re.join(", ")+(Ce?", custom":""):String(re)],["Email",be],["Storage",Ae],["Monitoring",Re],["Analytics",we],["SMS",Ne],["Deploy Target",X],["Docs Framework",T]];n?ct.forEach(([g,S],k)=>{p(!0,{event:"step",step:g,value:S,index:k+1,total:ct.length})}):ct.forEach(([g,S],k)=>{Xt({index:k+1,total:ct.length,label:g,value:S})});let Ro={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""},wo=Date.now();if(r){let g=re.length,S=[`clone template \u2192 ${i}`,"write nebutra.config.json",`prune template (orm=${De}, i18n=${st})`,`region \u2192 ${f}`,`auth \u2192 ${L==="none"?"skip (remove packages/auth)":`configure ${L}`}`,...M.length>0?[`social-login \u2192 generate ${M.length} callback route${M.length===1?"":"s"} + SocialLoginButtons.tsx (${M.join(", ")})`]:[],`db \u2192 ${q==="none"?"skip (remove packages/db)":`configure Prisma for ${q}`}`,`payment \u2192 ${W==="none"?"skip (remove packages/billing)":`configure ${W}`}`,...T!=="none"?[`docs \u2192 scaffold apps/docs (${T==="fumadocs"?"fumadocs":`${T} \u2192 fumadocs fallback`})`]:[],...g>0||Ce?[`ai-providers \u2192 generate registry.ts + env (${g}${Ce?" + custom":""} provider${g===1&&!Ce?"":"s"})`]:[],...be!=="none"?[`email \u2192 configure ${be}`]:[],...Ae!=="none"?[`storage \u2192 configure ${Ae}`]:[],...Re!=="none"?[`monitoring \u2192 configure ${Re}`]:[],...we!=="none"?[`analytics \u2192 configure ${we}`]:[],...Ne!=="none"?[`sms \u2192 configure ${Ne}`]:[],...Fe!=="none"?[`queue \u2192 configure ${Fe}`]:[],...Ve!=="none"?[`search \u2192 configure ${Ve}`]:[],...Ke!=="none"?[`cache \u2192 configure ${Ke}`]:[],...Ye!=="none"?[`notifications \u2192 configure ${Ye}`]:[],...Be!=="none"?[`webhooks \u2192 configure ${Be}`]:[],...$e!=="none"?[`cms \u2192 configure ${$e}`]:[],...qe!=="none"?[`feature-flags \u2192 configure ${qe}`]:[],...Ge!=="none"?[`captcha \u2192 configure ${Ge}`]:[],`mcp \u2192 ${it==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${He==="off"?"disabled":He==="auto"?je!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,`compliance \u2192 inject ${f} 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)",...X!=="none"?[`deploy \u2192 inject ${X} config`]:[],"inject .env.local",t.install===!1?"skip install":`run ${m} install`,t.git===!1?"skip git init":"run git init"];if(n)S.forEach(k=>p(!0,{event:"plan",action:k})),p(!0,{event:"done",dryRun:!0});else{process.stdout.write(`
2894
- `+x.bold(`Dry run \u2014 planned actions:
2895
- `));for(let k of S)process.stdout.write(` \u2022 ${k}
2896
- `);process.stdout.write(x.dim(`
2896
+ `}async function wo(e,t){let{projectName:o,region:n}=t;try{let r=lt.join(e,".sailor");Re.existsSync(r)||Re.mkdirSync(r,{recursive:!0}),Re.writeFileSync(lt.join(r,"next-steps.md"),Ui(o,n))}catch(r){let s=r instanceof Error?r.message:String(r);console.warn(`[create-sailor] Failed to write .sailor/next-steps.md: ${s}`)}try{let r=lt.join(e,"apps","web");if(!Re.existsSync(r))return;let s=lt.join(r,"src","app","[locale]","welcome");Re.existsSync(s)||Re.mkdirSync(s,{recursive:!0}),Re.writeFileSync(lt.join(s,"page.tsx"),Oi(o))}catch(r){let s=r instanceof Error?r.message:String(r);console.warn(`[create-sailor] Failed to write welcome page: ${s}`)}}var Ro="create-sailor";function p(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2897
+ `)}function Di(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function No(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 xo(e){return e==="drizzle"?"drizzle":e==="none"?"none":"prisma"}function ko(e){return e==="lemon"||e==="lemonsqueezy"?"lemonsqueezy":e==="none"?"none":"stripe"}function To(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 Oo(e){if(!e)return"clerk";let t=e.toLowerCase();return t==="betterauth"||t==="better-auth"?"betterauth":t==="none"?"none":"clerk"}function Uo(e){if(!e)return["openai"];let t=e.split(",").map(o=>o.trim().toLowerCase());return t.includes("none")?[]:t}var Lo={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function Mo(e,t){if(!e)return"fumadocs";let o=e.toLowerCase();if(o==="fumadocs"||o==="none")return o;if(o in Lo){let n=Lo[o];return t?p(!0,{event:"notice",kind:"docs-fallback",requested:o,effective:"fumadocs"}):process.stdout.write(R.yellow(`\u26A0 ${n} support is coming in v1.2. Falling back to fumadocs.
2898
+ `)+R.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
2899
+ `)),"fumadocs"}return"fumadocs"}function Do(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 Fo(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function Fi(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 jo(e){return e==="cn"?"wechat":"stripe"}async function ji(){let e=new Li;e.name(Ro).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(ne,"-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 | drizzle | none").option("--db <id>","postgres | mysql | sqlite | none").option("--auth <id>","clerk | betterauth | 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 <ids>","comma-separated provider ids").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 | 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 | upstash | 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("--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&&(on(),process.exit(0));let n=!!t.json,r=!!t.dryRun,s=!!t.yes,a=s||!process.stdin.isTTY;n||en(),p(n,{event:"start",version:ne});let c=o??(s?"./my-saas-app":void 0),i;if(c)i=c;else if(a)i="./my-saas-app";else{let m=await C.group({name:()=>C.text({message:"Where should we create your project?",placeholder:"./my-saas-app",defaultValue:"./my-saas-app",validate:y=>{if(y.length===0)return"Please enter a path."}})},{onCancel:()=>{process.stdout.write(R.red(`\u2718 Cancelled
2900
+ `)),process.exit(130)}});i=String(m.name)}let d=dt.basename(dt.resolve(i)),u=t.pm??Di(),S=!!t.region,U=!!t.auth,F=!!t.payment,ee=!!t.ai,Xe=!!t.email,E=!!t.storage,l=!!t.monitoring,N=!!t.analytics,ut=!!t.sms,Qt=t.i18n!==void 0,f,ze,z,Qe,j,k,$=fn(t.socialLogin),te,Ne,Q,V,mt;if(a){f=Fo(t.region),ze=xo(t.orm),z=No(t.db);let m=F?t.payment:jo(f);Qe=ko(m),j=To(m),k=Oo(t.auth),te=Uo(t.ai),Q=Do(t.deploy),V=Mo(t.docs,n),mt=Qt?!!t.i18n:!0}else{let m={};if(S||(m.region=()=>C.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"})),U||(m.auth=()=>C.select({message:"Auth provider?",options:[{value:"clerk",label:"Clerk"},{value:"betterauth",label:"Better Auth"},{value:"none",label:"None"}],initialValue:"clerk"})),!ee){let yt=Array.from(new Set(ht.map(w=>w.category)));m.aiCategories=()=>C.multiselect({message:"Which AI Provider categories do you want to explore? (Select multiple)",options:yt.map(w=>({value:w,label:w})),initialValues:["\u76F4\u63A5\u5B9E\u9A8C\u5BA4","\u7EDF\u4E00\u7F51\u5173"]}),m.aiProviders=({results:w})=>{let $e=w.aiCategories||[],_=ht.filter(K=>$e.includes(K.category)).map(K=>({value:K.id,label:`[${K.category}] ${K.name}`}));return _.push({value:"custom",label:"[\u81EA\u5B9A\u4E49] Custom OpenAI-compatible endpoint"}),C.multiselect({message:"Select AI Providers (Space to select, Enter to submit)",options:_,initialValues:["openai","anthropic"],required:!1})},m.enableCustom=({results:w})=>w.aiProviders?.includes("custom")?C.confirm({message:"Configure custom OpenAI-compatible endpoint?",initialValue:!0}):Promise.resolve(!1),m.customAiName=({results:w})=>w.enableCustom?C.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),m.customAiBaseUrl=({results:w})=>w.enableCustom?C.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:$e=>{if($e.length===0)return"Base URL is required."}}):Promise.resolve(void 0),m.customAiApiKeyEnv=({results:w})=>w.enableCustom?C.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0)}let y=Object.keys(m).length>0?await C.group(m,{onCancel:()=>{process.stdout.write(R.red(`\u2718 Cancelled
2901
+ `)),process.exit(130)}}):{};f=Fo(S?t.region:y.region),ze=xo(t.orm),z=No(t.db);let L=F?t.payment:jo(f);Qe=ko(L),j=To(L),k=Oo(U?t.auth:y.auth),te=ee?Uo(t.ai):y.aiProviders?.filter(yt=>yt!=="custom")??[],y.enableCustom&&(Ne={name:y.customAiName,baseURL:y.customAiBaseUrl,apiKeyEnvName:y.customAiApiKeyEnv}),Q=Do(t.deploy),V=Mo(t.docs,n),mt=Qt?!!t.i18n:!0}let P=Fi(f),xe=Xe?t.email:P.email,ke=E?t.storage:P.storage,Te=l?t.monitoring:P.monitoring,Oe=N?t.analytics:P.analytics,Ue=ut?t.sms:P.sms,Le=t.queue??P.queue,Me=t.search??P.search,Je=t.cache??P.cache,De=t.notifications??P.notifications,Fe=t.webhooks??P.webhooks,Ze=t.cms??P.cms,je=t.featureFlags??P.featureFlags,Ve=t.captcha??P.captcha,gt=t.mcp??P.mcp,et=t.metering??P.metering,Ke=t.billingMode??P.billingMode,Be=t.idp??P.idp,tt=tn([{flag:"queue",provider:Le},{flag:"search",provider:Me},{flag:"notifications",provider:De},{flag:"webhooks",provider:Fe},{flag:"feature-flags",provider:je},{flag:"captcha",provider:Ve}]);function Ut(){for(let m of tt)if(n)p(!0,{event:"warn",step:m.flag,provider:m.provider,packageStatus:m.status,message:qe(m.status)});else{let y=St(m.status);process.stdout.write(R.yellow(`\u26A0 ${m.flag}=${m.provider} ${y} \u2014 ${qe(m.status)}
2902
+ `))}}let Ye={region:f,orm:ze,database:z,payment:Qe,aiProviders:te,customAiEndpoint:Ne,deployTarget:Q,docs:V,i18n:mt,email:xe,storage:ke,monitoring:Te,analytics:Oe,sms:Ue,queue:Le,search:Me,cache:Je,notifications:De,webhooks:Fe,cms:Ze,featureFlags:je,captcha:Ve,mcp:gt,metering:et,billingMode:Ke,idp:Be},ft=[["Project name",d],["Region",f],["Auth",k],["Social login",$.length>0?$.map(m=>nt.find(y=>y.id===m)?.name??m).join(", "):"none"],["ORM",ze],["Database",z],["Payment",j],["AI",Array.isArray(te)?te.join(", ")+(Ne?", custom":""):String(te)],["Email",xe],["Storage",ke],["Monitoring",Te],["Analytics",Oe],["SMS",Ue],["Deploy Target",Q],["Docs Framework",V]];n?ft.forEach(([m,y],L)=>{p(!0,{event:"step",step:m,value:y,index:L+1,total:ft.length})}):ft.forEach(([m,y],L)=>{sn({index:L+1,total:ft.length,label:m,value:y})});let Vo={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""},Jt=Date.now();if(r){let m=te.length,y=[`clone template \u2192 ${i}`,"write nebutra.config.json",`prune template (orm=${ze}, i18n=${mt})`,`region \u2192 ${f}`,`auth \u2192 ${k==="none"?"skip (remove packages/auth)":`configure ${k}`}`,...$.length>0?[`social-login \u2192 generate ${$.length} callback route${$.length===1?"":"s"} + SocialLoginButtons.tsx (${$.join(", ")})`]:[],`db \u2192 ${z==="none"?"skip (remove packages/db)":`configure Prisma for ${z}`}`,`payment \u2192 ${j==="none"?"skip (remove packages/billing)":`configure ${j}`}`,...V!=="none"?[`docs \u2192 scaffold apps/docs (${V==="fumadocs"?"fumadocs":`${V} \u2192 fumadocs fallback`})`]:[],...m>0||Ne?[`ai-providers \u2192 generate registry.ts + env (${m}${Ne?" + custom":""} provider${m===1&&!Ne?"":"s"})`]:[],...xe!=="none"?[`email \u2192 configure ${xe}`]:[],...ke!=="none"?[`storage \u2192 configure ${ke}`]:[],...Te!=="none"?[`monitoring \u2192 configure ${Te}`]:[],...Oe!=="none"?[`analytics \u2192 configure ${Oe}`]:[],...Ue!=="none"?[`sms \u2192 configure ${Ue}`]:[],...Le!=="none"?[`queue \u2192 configure ${Le}`]:[],...Me!=="none"?[`search \u2192 configure ${Me}`]:[],...Je!=="none"?[`cache \u2192 configure ${Je}`]:[],...De!=="none"?[`notifications \u2192 configure ${De}`]:[],...Fe!=="none"?[`webhooks \u2192 configure ${Fe}`]:[],...Ze!=="none"?[`cms \u2192 configure ${Ze}`]:[],...je!=="none"?[`feature-flags \u2192 configure ${je}`]:[],...Ve!=="none"?[`captcha \u2192 configure ${Ve}`]:[],`mcp \u2192 ${gt==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${et==="off"?"disabled":et==="auto"?Qe!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...Ke!=="usage"?[`billing-mode \u2192 ${Ke}`]:[],...Be!=="clerk"?[`idp \u2192 ${Be}`]:[],`compliance \u2192 inject ${f} 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)",...Q!=="none"?[`deploy \u2192 inject ${Q} config`]:[],"inject .env.local",t.install===!1?"skip install":`run ${u} install`,t.git===!1?"skip git init":"run git init"];if(n)y.forEach(L=>p(!0,{event:"plan",action:L})),Ut(),p(!0,{event:"done",dryRun:!0});else{process.stdout.write(`
2903
+ `+R.bold(`Dry run \u2014 planned actions:
2904
+ `));for(let L of y)process.stdout.write(` \u2022 ${L}
2905
+ `);tt.length>0&&(process.stdout.write(`
2906
+ `+R.bold(R.yellow(`Preview-status providers selected:
2907
+ `))),Ut()),process.stdout.write(R.dim(`
2897
2908
  No files were written.
2898
- `))}process.exit(0)}let No=async()=>{process.stdout.write(`
2899
- `+x.red(`\u2718 Cancelled
2900
- `)),go.existsSync(i)&&await P.confirm({message:`Cleanup partial install at ${i}?`,initialValue:!0})===!0&&(go.rmSync(i,{recursive:!0,force:!0}),process.stdout.write(x.dim(` \u2713 Removed ${i}
2901
- `))),process.exit(130)};process.on("SIGINT",No);try{p(n,{event:"step",step:"clone",status:"start"}),await bn(i),p(n,{event:"step",step:"clone",status:"ok"}),p(n,{event:"step",step:"package",status:"start"}),await Nn(i,d),p(n,{event:"step",step:"package",status:"ok"}),p(n,{event:"step",step:"config",status:"start"}),await cn(i,at),p(n,{event:"step",step:"config",status:"ok"}),p(n,{event:"step",step:"prune",status:"start"}),await jn(i,at),p(n,{event:"step",step:"prune",status:"ok"}),p(n,{event:"step",step:"auth",choice:L,status:"start"}),await tn(i,L),p(n,{event:"step",step:"auth",choice:L,status:"ok"}),M.length>0?(p(n,{event:"step",step:"social-login",providers:M,status:"start"}),await sn(i,M,L),p(n,{event:"step",step:"social-login",providers:M,status:"ok"})):p(n,{event:"step",step:"social-login",status:"skip"}),p(n,{event:"step",step:"db",choice:q,status:"start"}),await dn(i,q,d),p(n,{event:"step",step:"db",choice:q,status:"ok"}),p(n,{event:"step",step:"payment",choice:W,status:"start"}),await Tn(i,W),p(n,{event:"step",step:"payment",choice:W,status:"ok"}),await En(i,be,f),n&&p(!0,{event:"step",step:"email",choice:be,status:"ok"}),await Bn(i,Ae,f),n&&p(!0,{event:"step",step:"storage",choice:Ae,status:"ok"}),await wn(i,Re,f),n&&p(!0,{event:"step",step:"monitoring",choice:Re,status:"ok"}),await Jt(i,we,f),n&&p(!0,{event:"step",step:"analytics",choice:we,status:"ok"}),await Kn(i,Ne,f),n&&p(!0,{event:"step",step:"sms",choice:Ne,status:"ok"}),await Gn(i,Fe,f),n&&p(!0,{event:"step",step:"queue",choice:Fe,status:"ok"}),await Xn(i,Ve,f),n&&p(!0,{event:"step",step:"search",choice:Ve,status:"ok"}),await Jn(i,Ke,f),n&&p(!0,{event:"step",step:"cache",choice:Ke,status:"ok"}),await eo(i,Ye,f),n&&p(!0,{event:"step",step:"notifications",choice:Ye,status:"ok"}),await no(i,Be,f),n&&p(!0,{event:"step",step:"webhooks",choice:Be,status:"ok"}),await ro(i,$e,f),n&&p(!0,{event:"step",step:"cms",choice:$e,status:"ok"}),await io(i,qe,f),n&&p(!0,{event:"step",step:"feature-flags",choice:qe,status:"ok"}),await co(i,Ge,f),n&&p(!0,{event:"step",step:"captcha",choice:Ge,status:"ok"}),await po(i,it),n&&p(!0,{event:"step",step:"mcp",mode:it,status:"ok"}),await uo(i,He,je),n&&p(!0,{event:"step",step:"metering",mode:He,status:"ok"}),await an(i,f),n&&p(!0,{event:"step",step:"compliance",region:f,status:"ok"}),await _n(i),await Fn(i,L),await mo(i,{projectName:d,region:f}),p(n,{event:"step",step:"ai-providers",status:"start"});let g={providerIds:at.aiProviders,customEndpoint:at.customAiEndpoint},S=Yt.join(i,"packages/ai-providers/templates");if(await Mn(i,g,S),p(n,{event:"step",step:"ai-providers",status:"ok"}),p(n,{event:"step",step:"docs",status:"start"}),T!=="none"?(await gn(i,{framework:T,projectName:d}),p(n,{event:"step",step:"docs",framework:"fumadocs",requested:T,status:"ok"})):p(n,{event:"step",step:"docs",status:"skip"}),p(n,{event:"step",step:"deploy-target",status:"start"}),X!=="none"&&await un(i,X),p(n,{event:"step",step:"deploy-target",status:"ok"}),p(n,{event:"step",step:"env",status:"start"}),await In(i,Ro),p(n,{event:"step",step:"env",status:"ok"}),t.install!==!1){let D=m==="bun"?"bun install":`${m} install`;n?p(!0,{event:"step",step:"install",pm:m,status:"start"}):process.stdout.write(x.dim(` Installing dependencies with ${m}\u2026
2902
- `));try{At(D,{cwd:i,stdio:n?"ignore":"inherit"}),p(n,{event:"step",step:"install",status:"ok"})}catch(xe){let lt=xe instanceof Error?xe.message:String(xe);n?p(!0,{event:"step",step:"install",status:"error",error:lt}):process.stdout.write(x.yellow(` \u26A0 install failed \u2014 run '${D}' manually.
2903
- `))}}else p(n,{event:"step",step:"install",status:"skip"});if(t.git!==!1){n&&p(!0,{event:"step",step:"git-init",status:"start"});try{At("git init -q",{cwd:i,stdio:"ignore"}),At("git add -A",{cwd:i,stdio:"ignore"}),At('git -c user.email=you@example.com -c user.name="You" commit -q -m "chore: initial scaffold from create-sailor"',{cwd:i,stdio:"ignore"}),p(n,{event:"step",step:"git-init",status:"ok"})}catch(D){let xe=D instanceof Error?D.message:String(D);n?p(!0,{event:"step",step:"git-init",status:"error",error:xe}):process.stdout.write(x.yellow(` \u26A0 git init skipped \u2014 not fatal.
2904
- `))}}else p(n,{event:"step",step:"git-init",status:"skip"});let v=Math.max(1,Math.round((Date.now()-wo)/1e3));n?p(!0,{event:"done",status:"ok",elapsedSec:v,targetDir:i}):Gt({elapsedSec:v,targetDir:i,skippedInstall:t.install===!1});try{li({pkg:{name:fo,version:se},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}process.exit(0)}catch(g){let S=g instanceof Error?g.message:String(g);n?p(!0,{event:"error",message:S}):process.stdout.write(x.red(`
2905
- \u2718 Failed: ${S}
2906
- `)),process.exit(1)}}mi().catch(e=>{process.stderr.write(String(e)+`
2909
+ `))}process.exit(0)}let Ko=async()=>{process.stdout.write(`
2910
+ `+R.red(`\u2718 Cancelled
2911
+ `)),ue.existsSync(i)&&await C.confirm({message:`Cleanup partial install at ${i}?`,initialValue:!0})===!0&&(ue.rmSync(i,{recursive:!0,force:!0}),process.stdout.write(R.dim(` \u2713 Removed ${i}
2912
+ `))),process.exit(130)};process.on("SIGINT",Ko);try{p(n,{event:"step",step:"clone",status:"start"}),await Wn(i),p(n,{event:"step",step:"clone",status:"ok"}),p(n,{event:"step",step:"package",status:"start"}),await oo(i,d),p(n,{event:"step",step:"package",status:"ok"}),p(n,{event:"step",step:"config",status:"start"}),await An(i,Ye),p(n,{event:"step",step:"config",status:"ok"}),p(n,{event:"step",step:"prune",status:"start"}),await mo(i,Ye),p(n,{event:"step",step:"prune",status:"ok"});let m=dt.join(i,"packages/db/prisma/schema.prisma");if(ue.existsSync(m)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let b=ue.readFileSync(m,"utf-8"),_=Gt(b,{auth:k,payment:j,"billing-mode":Ke,idp:Be,template:"saas"});ue.writeFileSync(m,_),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(b){let _=b instanceof Error?b.message:String(b);p(n,{event:"step",step:"schema-prune",status:"error",error:_})}}else p(n,{event:"step",step:"schema-prune",status:"skip"});if(p(n,{event:"step",step:"auth",choice:k,status:"start"}),await mn(i,k),p(n,{event:"step",step:"auth",choice:k,status:"ok"}),$.length>0?(p(n,{event:"step",step:"social-login",providers:$,status:"start"}),await Sn(i,$,k),p(n,{event:"step",step:"social-login",providers:$,status:"ok"})):p(n,{event:"step",step:"social-login",status:"skip"}),p(n,{event:"step",step:"db",choice:z,status:"start"}),await Nn(i,z,d),p(n,{event:"step",step:"db",choice:z,status:"ok"}),p(n,{event:"step",step:"payment",choice:j,status:"start"}),await so(i,j),p(n,{event:"step",step:"payment",choice:j,status:"ok"}),await Mn(i,xe,f),n&&p(!0,{event:"step",step:"email",choice:xe,status:"ok"}),await Io(i,ke,f),n&&p(!0,{event:"step",step:"storage",choice:ke,status:"ok"}),await eo(i,Te,f),n&&p(!0,{event:"step",step:"monitoring",choice:Te,status:"ok"}),await ln(i,Oe,f),n&&p(!0,{event:"step",step:"analytics",choice:Oe,status:"ok"}),await Po(i,Ue,f),n&&p(!0,{event:"step",step:"sms",choice:Ue,status:"ok"}),await yo(i,Le,f),n&&p(!0,{event:"step",step:"queue",choice:Le,status:"ok"}),await ho(i,Me,f),n&&p(!0,{event:"step",step:"search",choice:Me,status:"ok"}),await vn(i,Je,f),n&&p(!0,{event:"step",step:"cache",choice:Je,status:"ok"}),await no(i,De,f),n&&p(!0,{event:"step",step:"notifications",choice:De,status:"ok"}),await Ao(i,Fe,f),n&&p(!0,{event:"step",step:"webhooks",choice:Fe,status:"ok"}),await In(i,Ze,f),n&&p(!0,{event:"step",step:"cms",choice:Ze,status:"ok"}),await Yn(i,je,f),n&&p(!0,{event:"step",step:"feature-flags",choice:je,status:"ok"}),await Pn(i,Ve,f),n&&p(!0,{event:"step",step:"captcha",choice:Ve,status:"ok"}),await Xn(i,gt),n&&p(!0,{event:"step",step:"mcp",mode:gt,status:"ok"}),await Qn(i,et,Qe),n&&p(!0,{event:"step",step:"metering",mode:et,status:"ok"}),Ye.orm==="prisma"&&Ye.database!=="none"){let b=dt.join(i,"packages/db/prisma/schema.prisma");if(ue.existsSync(b)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let _=ue.readFileSync(b,"utf8"),K=Gt(_,{auth:k,payment:j,"billing-mode":Ke,idp:Be,template:"saas"});ue.writeFileSync(b,K),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(_){let K=_ instanceof Error?_.message:String(_);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"});p(n,{event:"step",step:"billing-mode",choice:Ke,status:"ok"}),p(n,{event:"step",step:"idp",choice:Be,status:"ok"}),await Cn(i,f),n&&p(!0,{event:"step",step:"compliance",region:f,status:"ok"}),await Kn(i),await vo(i,k),await wo(i,{projectName:d,region:f}),p(n,{event:"step",step:"ai-providers",status:"start"});let y={providerIds:Ye.aiProviders,customEndpoint:Ye.customAiEndpoint},L=dt.join(i,"packages/ai-providers/templates");if(await lo(i,y,L),p(n,{event:"step",step:"ai-providers",status:"ok"}),p(n,{event:"step",step:"docs",status:"start"}),V!=="none"?(await Tn(i,{framework:V,projectName:d}),p(n,{event:"step",step:"docs",framework:"fumadocs",requested:V,status:"ok"})):p(n,{event:"step",step:"docs",status:"skip"}),p(n,{event:"step",step:"deploy-target",status:"start"}),Q!=="none"&&await xn(i,Q),p(n,{event:"step",step:"deploy-target",status:"ok"}),p(n,{event:"step",step:"env",status:"start"}),await Fn(i,Vo),p(n,{event:"step",step:"env",status:"ok"}),t.install!==!1){let b=u==="bun"?"bun install":`${u} install`;n?p(!0,{event:"step",step:"install",pm:u,status:"start"}):process.stdout.write(R.dim(` Installing dependencies with ${u}\u2026
2913
+ `));try{Ot(b,{cwd:i,stdio:n?"ignore":"inherit"}),p(n,{event:"step",step:"install",status:"ok"})}catch(_){let K=_ instanceof Error?_.message:String(_);n?p(!0,{event:"step",step:"install",status:"error",error:K}):process.stdout.write(R.yellow(` \u26A0 install failed \u2014 run '${b}' manually.
2914
+ `))}}else p(n,{event:"step",step:"install",status:"skip"});if(t.git!==!1){n&&p(!0,{event:"step",step:"git-init",status:"start"});try{Ot("git init -q",{cwd:i,stdio:"ignore"}),Ot("git add -A",{cwd:i,stdio:"ignore"}),Ot('git -c user.email=you@example.com -c user.name="You" commit -q -m "chore: initial scaffold from create-sailor"',{cwd:i,stdio:"ignore"}),p(n,{event:"step",step:"git-init",status:"ok"})}catch(b){let _=b instanceof Error?b.message:String(b);n?p(!0,{event:"step",step:"git-init",status:"error",error:_}):process.stdout.write(R.yellow(` \u26A0 git init skipped \u2014 not fatal.
2915
+ `))}}else p(n,{event:"step",step:"git-init",status:"skip"});let $e=Math.max(1,Math.round((Date.now()-Jt)/1e3));an({template_version:ne,package_manager:u,region:f,auth:k,payment:j,ai_providers:te,deploy_target:Q,duration_ms:Date.now()-Jt}),tt.length>0&&Ut(),n?p(!0,{event:"done",status:"ok",elapsedSec:$e,targetDir:i,previewSelections:tt}):nn({elapsedSec:$e,targetDir:i,skippedInstall:t.install===!1,previewSelections:tt});try{Mi({pkg:{name:Ro,version:ne},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}process.exit(0)}catch(m){let y=m instanceof Error?m.message:String(m);n?p(!0,{event:"error",message:y}):process.stdout.write(R.red(`
2916
+ \u2718 Failed: ${y}
2917
+ `)),process.exit(1)}}ji().catch(e=>{process.stderr.write(String(e)+`
2907
2918
  `),process.exit(1)});