create-sailor 1.3.0 → 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 +211 -176
  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 Je}from"child_process";import un from"fs";import pt from"path";import*as I from"@clack/prompts";import{Command as ts}from"commander";import T from"picocolors";import ns from"update-notifier";import xn from"cfonts";import Rn from"picocolors";import dt from"fs";import Ze from"path";import{fileURLToPath as Nn}from"url";function Tn(){try{let t=Ze.dirname(Nn(import.meta.url));for(let n=0;n<4;n++){let r=Ze.join(t,"package.json");if(dt.existsSync(r)){let o=dt.readFileSync(r,"utf-8"),s=JSON.parse(o);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=Ze.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var J=Tn();function ut(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${J}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
3
- `));return}xn.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(Rn.dim(` AI-Native SaaS Template \xB7 v${J} \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 M from"picocolors";function kn(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function mt(e){let t=kn(),n=t?"\u2693":"-",r=t?"\u25B8":"->",o=t?"\u2605":"*",s=t?"\u{1F4E7}":"*",c=["",` ${t?M.bold(`${n} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`):`${n} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`}`,"",` ${t?M.bold("Next:"):"Next:"}`,` ${r} cd ${e.targetDir}`];e.skippedInstall&&c.push(` ${r} pnpm install (if --no-install was set)`),c.push(` ${r} pnpm dev ${t?M.dim("\u2192 http://localhost:3000"):"-> http://localhost:3000"}`,"",` ${t?M.bold("Customize:"):"Customize:"}`,` ${r} pnpm sailor brand init ${t?M.dim("\u2192 your colors, logo, domain"):"-> your colors, logo, domain"}`,` ${r} pnpm sailor preset apply ${t?M.dim("\u2192 toggle features"):"-> toggle features"}`,` ${r} pnpm sailor add <feat> ${t?M.dim("\u2192 add queue/search/cache/..."):"-> add queue/search/cache/..."}`,"",` ${t?M.bold("Add more features later:"):"Add more features later:"}`,` ${r} sailor add payment --provider=wechat`,` ${r} sailor add email --provider=postmark`,` ${r} sailor add storage --provider=supabase`,` ${t?M.dim("(more providers: `sailor add --list`)"):"(more providers: `sailor add --list`)"}`,"",` ${t?M.bold("Ship faster:"):"Ship faster:"}`,` ${o} 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 On=`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,6 +28,25 @@ 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 [Foundation]
32
+ --search <id> meilisearch | typesense | algolia | pgvector | none [Foundation]
33
+ --cache <id> upstash-redis | vercel-kv | redis | dragonfly | none
34
+ --notifications <id> novu | knock | custom | none [Foundation]
35
+ --webhooks <id> svix | custom | none [Foundation]
36
+ --cms <id> sanity | contentful | strapi | 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
46
+
47
+ Sailor features:
48
+ --mcp <mode> on | off (default: on \u2014 Agent-friendly MCP server)
49
+ --metering <mode> auto | on | off (default: auto)
31
50
 
32
51
  Toggles:
33
52
  --i18n enable i18n (default: true)
@@ -47,9 +66,9 @@ Examples:
47
66
  $ npm create sailor@latest my-app --region=cn --auth=clerk
48
67
  $ npm create sailor@latest my-app --region=hybrid --ai=openai,deepseek
49
68
  $ npm create sailor@latest --dry-run --region=cn
50
- `;function gt(){process.stdout.write(On)}import qe from"picocolors";function ft(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Un(e){let t=ft()?"\u25B8":"->",n=`[${e.index}/${e.total}]`,r=e.label.padEnd(18," ");return ft()?`${qe.dim(n)} ${qe.bold(r)} ${qe.dim(t)} ${qe.cyan(e.value)}`:`${n} ${r} ${t} ${e.value}`}function yt(e){process.stdout.write(Un(e)+`
51
- `)}var Ge=[{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:[]}],hs=Ge.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});import Ie from"fs";import A from"path";var St=[{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:""}],vs=St.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Et(e){return St.find(t=>t.id===e)}function Ln(e){Ie.mkdirSync(e,{recursive:!0})}function j(e,t){Ln(A.dirname(e)),Ie.writeFileSync(e,t)}function Q(e,t){let n=A.join(e,".env.example");Ie.existsSync(n)?Ie.appendFileSync(n,`
52
- `+t):Ie.writeFileSync(n,t)}function Mn(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";
53
72
  /**
54
73
  * PostHog browser SDK \u2014 lazy-initialized on first access.
55
74
  */
@@ -74,7 +93,7 @@ export function initPostHog(): void {
74
93
  }
75
94
 
76
95
  export { posthog };
77
- `,n=`import { PostHog } from "posthog-node";
96
+ `,o=`import { PostHog } from "posthog-node";
78
97
 
79
98
  /**
80
99
  * PostHog server-side client. Remember to await client.shutdown() at the end
@@ -105,7 +124,7 @@ export async function captureServerEvent(
105
124
  ph.capture({ distinctId, event, properties });
106
125
  await ph.shutdown();
107
126
  }
108
- `,r=`"use client";
127
+ `,n=`"use client";
109
128
  /**
110
129
  * <AnalyticsProvider /> \u2014 wrap the app root to enable PostHog + auto page views.
111
130
  */
@@ -132,11 +151,11 @@ export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
132
151
 
133
152
  return <>{children}</>;
134
153
  }
135
- `;j(A.join(e,"src","lib","analytics","posthog.client.ts"),t),j(A.join(e,"src","lib","analytics","posthog.server.ts"),n),j(A.join(e,"src","components","analytics","AnalyticsProvider.tsx"),r)}function jn(){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
136
155
  POSTHOG_KEY=
137
156
  NEXT_PUBLIC_POSTHOG_KEY=
138
157
  NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
139
- `}function Dn(e){j(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";
140
159
  /**
141
160
  * Plausible script tag \u2014 lightweight, privacy-friendly analytics.
142
161
  */
@@ -156,10 +175,10 @@ export function PlausibleScript() {
156
175
  />
157
176
  );
158
177
  }
159
- `)}function Fn(){return`# Plausible \u2014 privacy-friendly analytics
178
+ `)}function or(){return`# Plausible \u2014 privacy-friendly analytics
160
179
  NEXT_PUBLIC_PLAUSIBLE_DOMAIN=
161
180
  NEXT_PUBLIC_PLAUSIBLE_SRC=https://plausible.io/js/script.js
162
- `}function Bn(e){j(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";
163
182
  /**
164
183
  * Umami analytics \u2014 self-hosted OR umami.is cloud.
165
184
  */
@@ -179,10 +198,10 @@ export function UmamiScript() {
179
198
  />
180
199
  );
181
200
  }
182
- `)}function Yn(){return`# Umami \u2014 self-hostable analytics
201
+ `)}function sr(){return`# Umami \u2014 self-hostable analytics
183
202
  NEXT_PUBLIC_UMAMI_WEBSITE_ID=
184
203
  NEXT_PUBLIC_UMAMI_SRC=https://cloud.umami.is/script.js
185
- `}function Kn(e){let t=`"use client";
204
+ `}function ir(e){let t=`"use client";
186
205
  import mixpanel from "mixpanel-browser";
187
206
 
188
207
  let initialized = false;
@@ -200,7 +219,7 @@ export function initMixpanel(): void {
200
219
  }
201
220
 
202
221
  export { mixpanel };
203
- `,n=`import Mixpanel from "mixpanel";
222
+ `,o=`import Mixpanel from "mixpanel";
204
223
 
205
224
  let client: Mixpanel.Mixpanel | null = null;
206
225
 
@@ -221,10 +240,10 @@ export function trackServer(
221
240
  if (!c) return;
222
241
  c.track(event, { distinct_id: distinctId, ...properties });
223
242
  }
224
- `;j(A.join(e,"src","lib","analytics","mixpanel.client.ts"),t),j(A.join(e,"src","lib","analytics","mixpanel.server.ts"),n)}function Vn(){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
225
244
  MIXPANEL_TOKEN=
226
245
  NEXT_PUBLIC_MIXPANEL_TOKEN=
227
- `}function $n(e){j(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";
228
247
  /**
229
248
  * \u767E\u5EA6\u7EDF\u8BA1 Baidu Tongji \u2014 hm.js \u57CB\u70B9\u811A\u672C.
230
249
  */
@@ -250,9 +269,9 @@ var _hmt = _hmt || [];
250
269
  />
251
270
  );
252
271
  }
253
- `)}function qn(){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
254
273
  NEXT_PUBLIC_BAIDU_STATS_ID=
255
- `}function Gn(e){j(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";
256
275
  /**
257
276
  * \u795E\u7B56\u5206\u6790 (Sensors Analytics) \u2014 sa-sdk-javascript \u5C01\u88C5.
258
277
  */
@@ -280,10 +299,10 @@ export function initSensors(): void {
280
299
  }
281
300
 
282
301
  export { sensors };
283
- `)}function Wn(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
302
+ `)}function dr(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
284
303
  NEXT_PUBLIC_SENSORS_SERVER_URL=
285
304
  NEXT_PUBLIC_SENSORS_APP_JS_URL=
286
- `}function Xn(e){j(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";
287
306
  /**
288
307
  * GrowingIO CDP \u2014 inline snippet installer.
289
308
  */
@@ -308,24 +327,24 @@ gdp("send");
308
327
  />
309
328
  );
310
329
  }
311
- `)}function Hn(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
330
+ `)}function mr(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
312
331
  NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID=
313
- `}async function ht(e,t,n="global"){let r=Et(t);if(!r||r.id==="none")return;let o=A.join(e,"apps","web");if(!Ie.existsSync(o))return;let s=r.id;try{switch(s){case"posthog":Mn(o),Q(e,jn());return;case"plausible":Dn(o),Q(e,Fn());return;case"umami":Bn(o),Q(e,Yn());return;case"mixpanel":Kn(o),Q(e,Vn());return;case"baidu":$n(o),Q(e,qn());return;case"sensors":Gn(o),Q(e,Wn());return;case"growingio":Xn(o),Q(e,Hn());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 Z from"path";function et(e){w.existsSync(e)&&w.rmSync(e,{recursive:!0,force:!0})}function _t(e,t){let n=Z.join(e,".env.example");w.existsSync(n)?w.appendFileSync(n,`
314
- `+t):w.writeFileSync(n,t)}function vt(e,t){if(!w.existsSync(e))return;let n=w.readFileSync(e,"utf8"),r=n.replace(/export type AuthProviderId\s*=\s*"[^"]+"\s*\|\s*"[^"]+";/,`export type AuthProviderId = "${t}";`);r!==n&&w.writeFileSync(e,r)}function zn(e,t){let n=Z.join(e,"README.md");if(!w.existsSync(n)){w.writeFileSync(n,t);return}w.appendFileSync(n,`
315
- `+t)}async function It(e,t){let n=Z.join(e,"packages","auth");if(!w.existsSync(n))return;if(t==="none"){et(n),zn(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,`
316
335
  ## Auth
317
336
 
318
337
  Auth was skipped at scaffold time (\`--auth=none\`). Add your preferred auth provider manually (e.g. Clerk, Better Auth, NextAuth).
319
- `);return}let r=Z.join(n,"src","providers"),o=Z.join(n,"src","types.ts");if(t==="clerk"){et(Z.join(r,"better-auth.ts")),vt(o,"clerk"),_t(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
320
339
  CLERK_PUBLISHABLE_KEY=
321
340
  CLERK_SECRET_KEY=
322
- `);return}if(t==="betterauth"){et(Z.join(r,"clerk.ts")),vt(o,"better-auth"),_t(e,`# Better Auth
341
+ `);return}if(t==="betterauth"){Mt(ge.join(n,"clerk.ts")),un(r,"better-auth"),dn(e,`# Better Auth
323
342
  BETTER_AUTH_SECRET=
324
343
  BETTER_AUTH_URL=http://localhost:3000
325
- `);return}}var Re=[{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"}],Jn=new Set(Re.map(e=>e.id));function Pt(e){return Re.find(t=>t.id===e)}function bt(e){if(!e)return[];let t=e.split(",").map(o=>o.trim().toLowerCase()).filter(Boolean);if(t.includes("none"))return[];let n=[],r=new Set;for(let o of t)Jn.has(o)&&!r.has(o)&&(n.push(o),r.add(o));return n}import te from"fs";import ee from"path";function Qn(e,t){let n=`// 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
326
345
  // Generated by create-sailor \u2014 OAuth callback for ${e.name}
327
346
  // Primary auth provider: ${t}
328
- // Docs: ${e.docs}`,r={wechat:` const tokenRes = await fetch(
347
+ // Docs: ${e.docs}`,n={wechat:` const tokenRes = await fetch(
329
348
  "${e.tokenEndpoint}?" +
330
349
  new URLSearchParams({
331
350
  appid: process.env.WECHAT_APP_ID ?? "",
@@ -426,7 +445,7 @@ BETTER_AUTH_URL=http://localhost:3000
426
445
  const token = (await tokenRes.json()) as { access_token?: string; uid?: string };
427
446
  if (!token.access_token) {
428
447
  return NextResponse.redirect(new URL("/login?error=weibo_token", req.url));
429
- }`};return`${n}
448
+ }`};return`${o}
430
449
  import { type NextRequest, NextResponse } from "next/server";
431
450
 
432
451
  export async function GET(req: NextRequest) {
@@ -437,7 +456,7 @@ export async function GET(req: NextRequest) {
437
456
  return NextResponse.redirect(new URL("/login?error=no_code", req.url));
438
457
  }
439
458
 
440
- ${r[e.id]}
459
+ ${n[e.id]}
441
460
 
442
461
  // TODO: fetch user profile from ${e.name} using the access token.
443
462
  // TODO: upsert the user into your primary auth provider (${t}).
@@ -447,7 +466,7 @@ ${r[e.id]}
447
466
  void state;
448
467
  return NextResponse.redirect(new URL("/dashboard", req.url));
449
468
  }
450
- `}function Zn(e){return`"use client";
469
+ `}function Sr(e){return`"use client";
451
470
 
452
471
  /**
453
472
  * SocialLoginButtons \u2014 generated by create-sailor.
@@ -467,7 +486,7 @@ interface SocialProvider {
467
486
  }
468
487
 
469
488
  const PROVIDERS: SocialProvider[] = [
470
- ${e.map(n=>` { id: ${JSON.stringify(n.id)}, name: ${JSON.stringify(n.name)}, href: ${JSON.stringify(`/api/auth/oauth/${n.id}`)} }`).join(`,
489
+ ${e.map(o=>` { id: ${JSON.stringify(o.id)}, name: ${JSON.stringify(o.name)}, href: ${JSON.stringify(`/api/auth/oauth/${o.id}`)} }`).join(`,
471
490
  `)},
472
491
  ];
473
492
 
@@ -490,17 +509,23 @@ export function SocialLoginButtons() {
490
509
  </div>
491
510
  );
492
511
  }
493
- `}function At(e){te.mkdirSync(e,{recursive:!0})}function er(e,t){let n=ee.join(e,".env.example");te.existsSync(n)?te.appendFileSync(n,`
494
- `+t):te.writeFileSync(n,t)}function tr(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,n=e.envVars.map(r=>`${r}=`).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(`
495
514
  `);return`${t}
496
- ${n}
497
- `}async function Ct(e,t,n){if(!t||t.length===0)return;let r=ee.join(e,"apps","web");if(!te.existsSync(r))return;let o=new Set,s=[];for(let d of t){if(o.has(d))continue;o.add(d);let m=Pt(d);m&&s.push(m)}if(s.length===0)return;for(let d of s)er(e,tr(d));let a=ee.join(r,"src","app","api","auth","callback");for(let d of s){let m=ee.join(a,d.id);At(m);let S=ee.join(m,"route.ts");te.writeFileSync(S,Qn(d,n))}let c=ee.join(r,"src","components","auth");At(c);let i=ee.join(c,"SocialLoginButtons.tsx");te.writeFileSync(i,Zn(s))}import P from"fs";import v from"path";var nr=v.join("apps","web"),tt=v.join("src","components","compliance"),ke=v.join("src","app","[locale]");function D(e){return v.join(e,nr)}function rr(e){P.mkdirSync(e,{recursive:!0})}function k(e,t){rr(v.dirname(e)),P.writeFileSync(e,t,"utf8")}function nt(e,t){let n=v.join(e,".env.example");if(P.existsSync(n)){if(P.readFileSync(n,"utf8").includes(t.split(`
498
- `)[0]??""))return;P.appendFileSync(n,`
515
+ ${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,`
499
524
  `+t+`
500
- `)}else P.writeFileSync(n,t+`
501
- `)}var Oe=`> **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.
502
527
  > Consult a qualified lawyer in every jurisdiction you operate in before publishing.
503
- > \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`,or=`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";
504
529
  import { IcpFooter } from "@/components/compliance/IcpFooter";
505
530
  import { PublicSecurityFooter } from "@/components/compliance/PublicSecurityFooter";
506
531
 
@@ -551,7 +576,7 @@ export function Footer({ region = "global" }: FooterProps) {
551
576
  </footer>
552
577
  );
553
578
  }
554
- `,sr=`export function IcpFooter() {
579
+ `,Ar=`export function IcpFooter() {
555
580
  const icp = process.env.NEXT_PUBLIC_ICP_BEIAN;
556
581
  if (!icp) return null;
557
582
  return (
@@ -565,7 +590,7 @@ export function Footer({ region = "global" }: FooterProps) {
565
590
  </a>
566
591
  );
567
592
  }
568
- `,ir=`export function PublicSecurityFooter() {
593
+ `,wr=`export function PublicSecurityFooter() {
569
594
  const psb = process.env.NEXT_PUBLIC_PSB_BEIAN;
570
595
  const psbCode = process.env.NEXT_PUBLIC_PSB_CODE;
571
596
  if (!psb) return null;
@@ -582,7 +607,7 @@ export function Footer({ region = "global" }: FooterProps) {
582
607
  </a>
583
608
  );
584
609
  }
585
- `,ar=`"use client";
610
+ `,Rr=`"use client";
586
611
 
587
612
  import { useCallback, useEffect, useState } from "react";
588
613
 
@@ -809,7 +834,7 @@ function CategoryRow({ id, title, description, checked, disabled, onChange }: Ca
809
834
  </label>
810
835
  );
811
836
  }
812
- `,cr=`interface AigcDisclaimerProps {
837
+ `,Nr=`interface AigcDisclaimerProps {
813
838
  className?: string;
814
839
  }
815
840
 
@@ -829,13 +854,13 @@ export function AigcDisclaimer({ className }: AigcDisclaimerProps) {
829
854
  </div>
830
855
  );
831
856
  }
832
- `,pr=`---
857
+ `,xr=`---
833
858
  title: Privacy Policy / \u9690\u79C1\u653F\u7B56
834
859
  description: How {{COMPANY_NAME}} collects, uses, shares, and protects personal information.
835
860
  lastUpdated: 2026-01-01
836
861
  ---
837
862
 
838
- ${Oe}
863
+ ${rt}
839
864
 
840
865
  # Privacy Policy / \u9690\u79C1\u653F\u7B56
841
866
 
@@ -974,13 +999,13 @@ or in-app notification before the change takes effect.
974
999
  **Data Controller / \u6570\u636E\u63A7\u5236\u8005:** {{COMPANY_NAME}}
975
1000
  **Address / \u5730\u5740:** {{COMPANY_ADDRESS}}
976
1001
  **Email / \u90AE\u7BB1:** {{COMPANY_CONTACT_EMAIL}}
977
- `,lr=`---
1002
+ `,kr=`---
978
1003
  title: Terms of Service / \u670D\u52A1\u6761\u6B3E
979
1004
  description: Terms governing your use of {{COMPANY_NAME}}.
980
1005
  lastUpdated: 2026-01-01
981
1006
  ---
982
1007
 
983
- ${Oe}
1008
+ ${rt}
984
1009
 
985
1010
  # Terms of Service / \u670D\u52A1\u6761\u6B3E
986
1011
 
@@ -1093,13 +1118,13 @@ conflict-of-laws principles. Disputes shall be resolved in the competent courts
1093
1118
  ## 11. Contact / \u8054\u7CFB\u65B9\u5F0F
1094
1119
 
1095
1120
  {{COMPANY_NAME}} \xB7 {{COMPANY_ADDRESS}} \xB7 {{COMPANY_CONTACT_EMAIL}}
1096
- `,dr=`---
1121
+ `,Tr=`---
1097
1122
  title: AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
1098
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
1099
1124
  lastUpdated: 2026-01-01
1100
1125
  ---
1101
1126
 
1102
- ${Oe}
1127
+ ${rt}
1103
1128
 
1104
1129
  # AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
1105
1130
 
@@ -1175,13 +1200,13 @@ human professional.
1175
1200
 
1176
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
1177
1202
  \u7528\u4E8E\u533B\u7597\u3001\u6CD5\u5F8B\u3001\u91D1\u878D\u6216\u5B89\u5168\u6538\u5173\u7684\u51B3\u7B56\u3002
1178
- `,ur=`---
1203
+ `,Or=`---
1179
1204
  title: Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
1180
1205
  description: Notice of cross-border transfer of personal information, per PIPL.
1181
1206
  lastUpdated: 2026-01-01
1182
1207
  ---
1183
1208
 
1184
- ${Oe}
1209
+ ${rt}
1185
1210
 
1186
1211
  # Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
1187
1212
 
@@ -1240,13 +1265,13 @@ Refusal may limit your ability to use features that rely on overseas services.
1240
1265
  - \u4F20\u8F93\u4E2D\u52A0\u5BC6 (TLS 1.2+) \u53CA\u9759\u6001\u52A0\u5BC6 (AES-256)\u3002
1241
1266
  - \u5408\u540C\u6761\u6B3E\u8981\u6C42\u5883\u5916\u63A5\u6536\u65B9\u63D0\u4F9B\u7B49\u540C\u4E8E PIPL \u7684\u4FDD\u62A4\u3002
1242
1267
  - \u8BBF\u95EE\u63A7\u5236\u3001\u5BA1\u8BA1\u65E5\u5FD7\u548C\u8FDD\u89C4\u901A\u77E5\u7A0B\u5E8F\u3002
1243
- `,mr=`---
1268
+ `,Ur=`---
1244
1269
  title: Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
1245
1270
  description: Itemized list of personal information collected, per PIPL Article 17.
1246
1271
  lastUpdated: 2026-01-01
1247
1272
  ---
1248
1273
 
1249
- ${Oe}
1274
+ ${rt}
1250
1275
 
1251
1276
  # Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
1252
1277
 
@@ -1282,19 +1307,19 @@ To exercise your rights (access, rectify, delete, export, withdraw consent), con
1282
1307
  **{{COMPANY_CONTACT_EMAIL}}**.
1283
1308
 
1284
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
1285
- `;async function gr(e,t){let n=D(e);if(!P.existsSync(n))return;let r=v.join(n,"src","components","compliance","Footer.tsx");k(r,or);let o=v.join(n,"src","components","compliance","README.md");k(o,["# 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(`
1286
- `))}async function fr(e,t){let n=D(e);if(!P.existsSync(n))return;let r=v.join(n,"src","components","compliance","CookieBanner.tsx");k(r,ar)}async function yr(e,t){let n=D(e);if(!P.existsSync(n))return;let r=v.join(n,ke,"privacy","page.mdx");k(r,pr)}async function Sr(e,t){let n=D(e);if(!P.existsSync(n))return;let r=v.join(n,ke,"terms","page.mdx");k(r,lr)}async function Er(e){let t=D(e);if(!P.existsSync(t))return;let n=v.join(t,tt,"IcpFooter.tsx");k(n,sr),nt(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(`
1287
- `))}async function hr(e){let t=D(e);if(!P.existsSync(t))return;let n=v.join(t,tt,"PublicSecurityFooter.tsx");k(n,ir),nt(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(`
1288
- `))}async function _r(e){let t=D(e);if(!P.existsSync(t))return;let n=v.join(t,tt,"AigcDisclaimer.tsx");k(n,cr),nt(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(`
1289
- `))}async function vr(e){let t=D(e);if(!P.existsSync(t))return;let n=v.join(t,ke,"aigc-disclosure","page.mdx");k(n,dr)}async function Ir(e){let t=D(e);if(!P.existsSync(t))return;let n=v.join(t,ke,"cross-border-data","page.mdx");k(n,ur)}async function Pr(e){let t=D(e);if(!P.existsSync(t))return;let n=v.join(t,ke,"pii-collection","page.mdx");k(n,mr)}async function wt(e,t){try{await gr(e,t),await fr(e,t),await yr(e,t),await Sr(e,t),(t==="cn"||t==="hybrid")&&(await Er(e),await hr(e),await _r(e),await vr(e),await Ir(e),await Pr(e))}catch(n){throw console.error("applyComplianceTemplates failed:",n),new Error(`Failed to apply compliance templates for region "${t}". Check that ${e} is writable.`)}}import br from"fs";import Ar from"path";async function Nt(e,t){let n=Ar.join(e,"nebutra.config.json");br.writeFileSync(n,JSON.stringify(t,null,2)+`
1290
- `)}import q from"fs";import rt from"path";function Cr(e){q.existsSync(e)&&q.rmSync(e,{recursive:!0,force:!0})}function Tt(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 xt(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 Nr(e,t){let n=rt.join(e,".env.example");q.existsSync(n)?q.appendFileSync(n,`
1291
- `+t):q.writeFileSync(n,t)}async function Rt(e,t,n){let r=rt.join(e,"packages","db");if(t==="none"){Cr(r);return}let o=rt.join(r,"prisma","schema.prisma"),s;if(t==="postgresql"?s=`postgresql://postgres:postgres@localhost:5432/${n}`:t==="mysql"?s=`mysql://root:root@localhost:3306/${n}`:s="file:./dev.db",Nr(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})
1292
1317
  DATABASE_URL="${s}"
1293
- `),!q.existsSync(o))return;let a=q.readFileSync(o,"utf8"),c=a;t==="mysql"?(c=Tt(c,"mysql"),c=xt(c)):t==="sqlite"&&(c=Tt(c,"sqlite"),c=wr(c),c=xt(c)),c!==a&&q.writeFileSync(o,c)}import Ue from"fs";import N from"path";import{fileURLToPath as Tr}from"url";var xr=Tr(import.meta.url),Rr=N.dirname(xr);async function kt(e,t){if(t==="none")return;let n=N.join(Rr,"../../templates/deploy");t==="vercel"?await Ue.promises.copyFile(N.join(n,"vercel.json"),N.join(e,"vercel.json")):t==="railway"?await Ue.promises.copyFile(N.join(n,"railway.toml"),N.join(e,"railway.toml")):t==="cloudflare"?await Ue.promises.copyFile(N.join(n,"wrangler.toml"),N.join(e,"wrangler.toml")):t==="selfhost"&&(await Ue.promises.copyFile(N.join(n,"docker-compose.yml"),N.join(e,"docker-compose.yml")),await Ue.promises.copyFile(N.join(n,"Dockerfile.web"),N.join(e,"Dockerfile.web")))}import G from"fs";import ne from"path";import{fileURLToPath as kr}from"url";var Or=kr(import.meta.url),Ot=ne.dirname(Or),Ur=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml)$/;function Lr(e){let t=[ne.join(Ot,"..","templates","docs",e),ne.join(Ot,"..","..","templates","docs",e)];for(let n of t)if(G.existsSync(n))return n;return t[0]}async function Ut(e,t){if(t.framework==="none")return;let n=(t.framework==="fumadocs","fumadocs"),r=Lr(n),o=ne.join(e,"apps","docs");if(!G.existsSync(r))throw new Error(`Docs template not found: ${r}`);Lt(r,o),Mt(o,{"{PRODUCT_NAME}":t.projectName})}function Lt(e,t){G.mkdirSync(t,{recursive:!0});for(let n of G.readdirSync(e,{withFileTypes:!0})){let r=ne.join(e,n.name),o=ne.join(t,n.name);n.isDirectory()?Lt(r,o):G.copyFileSync(r,o)}}function Mt(e,t){for(let n of G.readdirSync(e,{withFileTypes:!0})){let r=ne.join(e,n.name);if(n.isDirectory())Mt(r,t);else if(Ur.test(n.name)){let o=G.readFileSync(r,"utf-8");for(let[s,a]of Object.entries(t))o=o.split(s).join(a);G.writeFileSync(r,o)}}}import oe from"fs";import re from"path";var We=[{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 jt(e){return We.find(t=>t.id===e)}var Qs=We.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var se="@nebutra/email";function ot(e,t){oe.mkdirSync(re.dirname(e),{recursive:!0}),oe.writeFileSync(e,t)}function Mr(e,t){let n=re.join(e,".env.example");oe.existsSync(n)?oe.appendFileSync(n,`
1294
- `+t):oe.writeFileSync(n,t)}function jr(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,n=e.envVars.map(r=>`${r}=`).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(`
1295
1320
  `);return`${t}
1296
- ${n}
1297
- `}var Dr=`/**
1321
+ ${o}
1322
+ `}var ss=`/**
1298
1323
  * Public inputs accepted by the \`sendEmail\` wrapper.
1299
1324
  * Keep the surface minimal \u2014 individual providers may accept more, but
1300
1325
  * consumers should code against this shape for portability.
@@ -1314,8 +1339,8 @@ export interface SendEmailResult {
1314
1339
  /** Raw provider response \u2014 useful for debugging, not a stable contract. */
1315
1340
  raw?: unknown;
1316
1341
  }
1317
- `;function Fr(){return`/**
1318
- * @${se.slice(1)} \u2014 Resend transactional email wrapper.
1342
+ `;function is(){return`/**
1343
+ * @${ve.slice(1)} \u2014 Resend transactional email wrapper.
1319
1344
  *
1320
1345
  * Docs: https://resend.com/docs
1321
1346
  */
@@ -1353,8 +1378,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1353
1378
  }
1354
1379
 
1355
1380
  export type { SendEmailInput, SendEmailResult } from "./types.js";
1356
- `}function Br(){return`/**
1357
- * @${se.slice(1)} \u2014 Postmark transactional email wrapper.
1381
+ `}function as(){return`/**
1382
+ * @${ve.slice(1)} \u2014 Postmark transactional email wrapper.
1358
1383
  *
1359
1384
  * Docs: https://postmarkapp.com/developer
1360
1385
  */
@@ -1391,8 +1416,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1391
1416
  }
1392
1417
 
1393
1418
  export type { SendEmailInput, SendEmailResult } from "./types.js";
1394
- `}function Yr(){return`/**
1395
- * @${se.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1419
+ `}function cs(){return`/**
1420
+ * @${ve.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1396
1421
  *
1397
1422
  * Docs: https://docs.aws.amazon.com/ses
1398
1423
  */
@@ -1447,8 +1472,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1447
1472
  }
1448
1473
 
1449
1474
  export type { SendEmailInput, SendEmailResult } from "./types.js";
1450
- `}function Kr(){return`/**
1451
- * @${se.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.
1452
1477
  *
1453
1478
  * Docs: https://help.aliyun.com/product/29412.html
1454
1479
  */
@@ -1497,8 +1522,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1497
1522
  }
1498
1523
 
1499
1524
  export type { SendEmailInput, SendEmailResult } from "./types.js";
1500
- `}function Vr(){return`/**
1501
- * @${se.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1525
+ `}function ls(){return`/**
1526
+ * @${ve.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1502
1527
  *
1503
1528
  * Docs: https://cloud.tencent.com/document/product/1288
1504
1529
  */
@@ -1545,8 +1570,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1545
1570
  }
1546
1571
 
1547
1572
  export type { SendEmailInput, SendEmailResult } from "./types.js";
1548
- `}function $r(){return`/**
1549
- * @${se.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).
1550
1575
  *
1551
1576
  * Docs: https://qiye.163.com/help
1552
1577
  */
@@ -1583,21 +1608,23 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1583
1608
  }
1584
1609
 
1585
1610
  export type { SendEmailInput, SendEmailResult } from "./types.js";
1586
- `}function qr(e){switch(e){case"resend":return Fr();case"postmark":return Br();case"ses":return Yr();case"aliyun-dm":return Kr();case"tencent-ses":return Vr();case"netease":return $r();case"none":return`export {};
1587
- `}}function Gr(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),e.id==="aliyun-dm"&&(t["@alicloud/openapi-client"]="^0.4.12");let n={name:se,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(n,null,2)+`
1588
- `}async function Dt(e,t,n){if(t==="none")return;let r=jt(t);if(!r)throw new Error(`Unknown email provider "${t}". Valid ids: ${We.map(a=>a.id).join(", ")}`);let o=re.join(e,"packages","email"),s=re.join(o,"src");oe.existsSync(s)&&oe.rmSync(s,{recursive:!0,force:!0}),ot(re.join(o,"package.json"),Gr(r)),ot(re.join(s,"types.ts"),Dr),ot(re.join(s,"index.ts"),qr(r.id)),Mr(e,jr(r))}import Bt from"crypto";import Le from"fs";import Ft from"path";function ie(e){return Bt.randomBytes(e).toString("base64").replace(/=+$/,"")}function Wr(e){return Bt.randomBytes(e).toString("hex")}function Xr(){return{AUTH_SECRET:ie(32),NEXTAUTH_SECRET:ie(32),BETTER_AUTH_SECRET:ie(32),JWT_SECRET:ie(32),WEBHOOK_SECRET:Wr(16),ENCRYPTION_KEY:ie(32),API_SECRET_KEY:ie(32),SESSION_SECRET:ie(32)}}function Hr(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function zr(e,t,n){let r=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),o=Hr(n);return e.replace(r,`${t}="${o}"`)}async function Yt(e){let t=Ft.join(e,".env.example"),n=Ft.join(e,".env.local");if(!Le.existsSync(t))return null;try{let r=Le.readFileSync(t,"utf8"),o=Xr(),a=Le.existsSync(n)?Le.readFileSync(n,"utf8"):r;for(let c of Object.keys(o))a=zr(a,c,o[c]);return Le.writeFileSync(n,a),o}catch(r){let o=r instanceof Error?r.message:String(r);throw console.error(`[create-sailor] Failed to generate env secrets: ${o}`),new Error(`Unable to write .env.local: ${o}`)}}import Xe from"fs";import Kt from"path";async function Vt(e,t){let n=`# 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
1589
1614
  DATABASE_URL="${String(t.databaseUrl)}"
1590
1615
 
1591
1616
  NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="${String(t.clerkPublishable)}"
1592
1617
  CLERK_SECRET_KEY="${String(t.clerkSecret)}"
1593
1618
 
1594
1619
  NEXT_PUBLIC_SITE_URL="http://localhost:3000"
1595
- `,r=Kt.join(e,".env"),o=Kt.join(e,".env.local");!Xe.existsSync(r)&&!Xe.existsSync(o)?Xe.writeFileSync(o,n):Xe.appendFileSync(o,`
1596
- `+n)}import{execSync as Jr}from"child_process";import F from"fs";import Pe from"path";import Qr from"ignore";var Zr={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 eo(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function $t(e,t,n){let r=F.readdirSync(t,{withFileTypes:!0});for(let o of r){if(o.name==="node_modules"||o.name===".git")continue;let s=Pe.join(t,o.name),a=Pe.relative(e,s).split(Pe.sep).join("/");o.isDirectory()?(n.push(a+"/"),$t(e,s,n)):n.push(a)}}function to(e){let t=Pe.join(e,".templateignore");if(!F.existsSync(t))return;let n=F.readFileSync(t,"utf8"),r=Qr().add(n),o=[];$t(e,e,o);let s=o.map(i=>i.endsWith("/")?i.slice(0,-1):i),a=new Set(r.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=Pe.join(e,i);try{F.existsSync(d)&&F.rmSync(d,{recursive:!0,force:!0})}catch{}}try{F.existsSync(t)&&F.rmSync(t,{force:!0})}catch{}}function no(e,t){Jr(`set -o pipefail; curl -sSfL ${e} | tar -xz -C "${t}" --strip-components=1`,{stdio:"ignore",shell:"bash"})}async function qt(e){F.mkdirSync(e,{recursive:!0});let n=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],r;for(let o of n){let s=Zr[o],a=eo(s.repo,s.ref);try{if(no(a,e),s.applyIgnore)try{to(e)}catch(c){throw new Error(`Template cloned, but .templateignore processing failed: ${c instanceof Error?c.message:String(c)}`)}return}catch(c){r=c instanceof Error?c:new Error(String(c));try{let i=F.readdirSync(e);for(let d of i)F.rmSync(Pe.join(e,d),{recursive:!0,force:!0})}catch{}}}throw new Error(`Failed to download the template from any source. Last error: ${r?.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"}
1597
1622
 
1598
- Ensure you have internet access and curl/tar installed.
1599
- You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import be from"fs";import C from"path";var Gt=[{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:""}],yi=Gt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Wt(e){return Gt.find(t=>t.id===e)}function ro(e){be.mkdirSync(e,{recursive:!0})}function B(e,t){ro(C.dirname(e)),be.writeFileSync(e,t)}function Me(e,t){let n=C.join(e,".env.example");be.existsSync(n)?be.appendFileSync(n,`
1600
- `+t):be.writeFileSync(n,t)}function oo(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";
1601
1628
 
1602
1629
  Sentry.init({
1603
1630
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
@@ -1612,21 +1639,21 @@ Sentry.init({
1612
1639
  ],
1613
1640
  environment: process.env.NODE_ENV,
1614
1641
  });
1615
- `,n=`import * as Sentry from "@sentry/nextjs";
1642
+ `,o=`import * as Sentry from "@sentry/nextjs";
1616
1643
 
1617
1644
  Sentry.init({
1618
1645
  dsn: process.env.SENTRY_DSN ?? process.env.NEXT_PUBLIC_SENTRY_DSN,
1619
1646
  tracesSampleRate: 1.0,
1620
1647
  environment: process.env.NODE_ENV,
1621
1648
  });
1622
- `,r=`import * as Sentry from "@sentry/nextjs";
1649
+ `,n=`import * as Sentry from "@sentry/nextjs";
1623
1650
 
1624
1651
  Sentry.init({
1625
1652
  dsn: process.env.SENTRY_DSN ?? process.env.NEXT_PUBLIC_SENTRY_DSN,
1626
1653
  tracesSampleRate: 1.0,
1627
1654
  environment: process.env.NODE_ENV,
1628
1655
  });
1629
- `,o=`/**
1656
+ `,r=`/**
1630
1657
  * Next.js instrumentation hook \u2014 wires Sentry into Node and Edge runtimes.
1631
1658
  * See https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation
1632
1659
  */
@@ -1640,14 +1667,14 @@ export async function register() {
1640
1667
  }
1641
1668
 
1642
1669
  export { captureRequestError as onRequestError } from "@sentry/nextjs";
1643
- `;B(C.join(e,"sentry.client.config.ts"),t),B(C.join(e,"sentry.server.config.ts"),n),B(C.join(e,"sentry.edge.config.ts"),r),B(C.join(e,"instrumentation.ts"),o)}function so(){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
1644
1671
  # Get your DSN from https://sentry.io/settings/projects/<project>/keys/
1645
1672
  SENTRY_DSN=
1646
1673
  NEXT_PUBLIC_SENTRY_DSN=
1647
1674
  SENTRY_ORG=
1648
1675
  SENTRY_PROJECT=
1649
1676
  SENTRY_AUTH_TOKEN=
1650
- `}function io(e){let t=`/**
1677
+ `}function ks(e){let t=`/**
1651
1678
  * Next.js instrumentation hook \u2014 wires Datadog APM (dd-trace) into Node runtime.
1652
1679
  * Edge runtime is not supported by dd-trace; only nodejs is initialized.
1653
1680
  */
@@ -1664,7 +1691,7 @@ export async function register() {
1664
1691
  });
1665
1692
  }
1666
1693
  }
1667
- `,n=`"use client";
1694
+ `,o=`"use client";
1668
1695
  /**
1669
1696
  * Datadog RUM (Real User Monitoring) \u2014 browser-side tracking.
1670
1697
  * Initialize once in your root layout via <DatadogRumProvider />.
@@ -1695,7 +1722,7 @@ export function initDatadogRum(): void {
1695
1722
  });
1696
1723
  initialized = true;
1697
1724
  }
1698
- `;B(C.join(e,"instrumentation.ts"),t),B(C.join(e,"src","lib","monitoring","datadog-rum.ts"),n)}function ao(){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
1699
1726
  # Server APM (dd-trace)
1700
1727
  DD_API_KEY=
1701
1728
  DD_APP_KEY=
@@ -1710,7 +1737,7 @@ NEXT_PUBLIC_DD_SITE=datadoghq.com
1710
1737
  NEXT_PUBLIC_DD_SERVICE=sailor-web
1711
1738
  NEXT_PUBLIC_DD_ENV=production
1712
1739
  NEXT_PUBLIC_DD_VERSION=
1713
- `}function co(e){let t=`/**
1740
+ `}function Os(e){let t=`/**
1714
1741
  * Bugsnag server-side initialization.
1715
1742
  * Import this once at the top of your server entrypoint or a shared init module.
1716
1743
  */
@@ -1730,7 +1757,7 @@ export function startBugsnagServer(): void {
1730
1757
  });
1731
1758
  started = true;
1732
1759
  }
1733
- `,n=`"use client";
1760
+ `,o=`"use client";
1734
1761
  /**
1735
1762
  * Bugsnag browser initialization \u2014 wrap your app root with the returned provider.
1736
1763
  */
@@ -1759,11 +1786,11 @@ export function getBugsnagErrorBoundary() {
1759
1786
  errorBoundary = plugin.createErrorBoundary(React) as typeof errorBoundary;
1760
1787
  return errorBoundary;
1761
1788
  }
1762
- `;B(C.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),B(C.join(e,"src","lib","monitoring","bugsnag.client.tsx"),n)}function po(){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
1763
1790
  BUGSNAG_API_KEY=
1764
1791
  NEXT_PUBLIC_BUGSNAG_API_KEY=
1765
1792
  APP_VERSION=
1766
- `}function lo(e){B(C.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1793
+ `}function Ls(e){X(O.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1767
1794
  /**
1768
1795
  * \u963F\u91CC\u4E91 ARMS (Application Real-time Monitoring Service) browser agent.
1769
1796
  * Injects the official JS agent via next/script.
@@ -1784,11 +1811,11 @@ export function ArmsScript() {
1784
1811
  />
1785
1812
  );
1786
1813
  }
1787
- `)}function uo(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1814
+ `)}function Ms(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1788
1815
  ALIYUN_ARMS_LICENSE_KEY=
1789
1816
  ALIYUN_ARMS_APP_NAME=
1790
1817
  NEXT_PUBLIC_ARMS_PID=
1791
- `}function mo(e){B(C.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1818
+ `}function Ds(e){X(O.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1792
1819
  /**
1793
1820
  * \u542C\u4E91 Browser Agent (\u524D\u7AEF\u6027\u80FD\u76D1\u63A7).
1794
1821
  * Docs: https://www.tingyun.com/docs
@@ -1806,12 +1833,12 @@ export function TingYunScript() {
1806
1833
  />
1807
1834
  );
1808
1835
  }
1809
- `)}function go(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1836
+ `)}function Fs(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1810
1837
  TINGYUN_LICENSE_KEY=
1811
1838
  NEXT_PUBLIC_TINGYUN_APP_KEY=
1812
- `}async function Xt(e,t,n="global"){let r=Wt(t);if(!r||r.id==="none")return;let o=C.join(e,"apps","web");if(!be.existsSync(o))return;let s=r.id;try{switch(s){case"sentry":oo(o),Me(e,so());return;case"datadog":io(o),Me(e,ao());return;case"bugsnag":co(o),Me(e,po());return;case"aliyun-arms":lo(o),Me(e,uo());return;case"tingyun":mo(o),Me(e,go());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 st from"fs";import fo from"path";async function Ht(e,t){let n=fo.join(e,"package.json");if(st.existsSync(n)){let r=st.readFileSync(n,"utf8"),o=JSON.parse(r);o.name=t,o.version="0.1.0",st.writeFileSync(n,JSON.stringify(o,null,2)+`
1813
- `)}}import K from"fs";import je from"path";var yo=["stripe","lemonsqueezy","chinapay","polar"];function zt(e){K.existsSync(e)&&K.rmSync(e,{recursive:!0,force:!0})}function So(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function Eo(e,t){let n=je.join(e,".env.example");K.existsSync(n)?K.appendFileSync(n,`
1814
- `+t):K.writeFileSync(n,t)}function ho(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
1815
1842
  STRIPE_SECRET_KEY=
1816
1843
  STRIPE_WEBHOOK_SECRET=
1817
1844
  `;case"lemon":return`# Lemon Squeezy
@@ -1826,14 +1853,14 @@ CHINAPAY_WECHAT_ENABLED=true
1826
1853
  CHINAPAY_APP_ID=
1827
1854
  CHINAPAY_APP_SECRET=
1828
1855
  CHINAPAY_ALIPAY_ENABLED=true
1829
- `}}async function Jt(e,t){let n=je.join(e,"packages","billing");if(!K.existsSync(n))return;if(t==="none"){zt(n);return}let r=je.join(n,"src"),o=new Set(So(t));for(let a of yo)o.has(a)||zt(je.join(r,a));let s=je.join(r,"checkout","types.ts");if(K.existsSync(s)){let a=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",c=K.readFileSync(s,"utf8"),i=c.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${a}";`);i!==c&&K.writeFileSync(s,i)}Eo(e,ho(t))}import W from"fs";import Ae from"path";var en=new Set(["siliconflow","volcengine-ark","bailian","moonshot"]),it=/@sailor:([^\s*]+)/;function _o(e,t){let{providerIds:n,customEndpoint:r}=t;if(e.startsWith("provider:")){let o=e.slice(9);return{marker:e,keep:n.includes(o)}}if(e==="cn-compatible"){let o=n.some(s=>en.has(s));return{marker:e,keep:o||!!r}}if(e.startsWith("cn-instance:")){let o=e.slice(12);return{marker:e,keep:n.includes(o)}}return e==="custom-endpoint"?{marker:e,keep:!!r}:e==="registry-entries"?{marker:e,keep:!0}:{marker:e,keep:!0}}function Qt(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function Zt(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function tn(e,t){let n=e.split(`
1830
- `),r=[],o=e.includes("#"),s=0;for(;s<n.length;){let a=n[s],c=a.match(it);if(!c){r.push(a),s++;continue}let{marker:i,keep:d}=_o(c[1],t);if(i==="registry-entries"){r.push(o?Zt(a):Qt(a)),s++;continue}if(d){let m=o?Zt(a):Qt(a);m.trim().length>0&&r.push(m);let S=s+1;for(;S<n.length&&n[S].trim()!==""&&!it.test(n[S]);)r.push(n[S]),S++;S<n.length&&n[S].trim()===""&&(r.push(n[S]),S++),s=S}else{let m=s+1;for(;m<n.length&&n[m].trim()!==""&&!it.test(n[m]);)m++;m<n.length&&n[m].trim()===""&&m++,s=m}}return vo(r.join(`
1831
- `),t)}function vo(e,t){let{providerIds:n,customEndpoint:r}=t,o=new Set;for(let d of n)["openai","anthropic","google","mistral","xai"].includes(d)&&o.add(d),o.add(d.replace(/-/g,"_")),o.add(d);r&&o.add("custom");let s=/createProviderRegistry\(\{([\s\S]*?)\}\)/,a=e.match(s);if(!a)return e;let i=a[1].split(`
1832
- `).filter(d=>{let m=d.trim();if(m===""||m.startsWith("//"))return!0;let S=m.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return S?o.has(S[1]):!0}).join(`
1833
- `);return e.replace(s,`createProviderRegistry({${i}})`)}function Io(e,t){let n=Ae.join(t,"registry.ts.template"),r=W.readFileSync(n,"utf-8");return tn(r,e)}function Po(e,t){let n=Ae.join(t,".env.example.template"),r=W.readFileSync(n,"utf-8");return tn(r,e)}async function nn(e,t,n){let r=Io(t,n),o=Po(t,n),s=Ae.join(e,"packages/ai-sdk/src");await W.promises.mkdir(s,{recursive:!0}),await W.promises.writeFile(Ae.join(s,"registry.ts"),r),await W.promises.appendFile(Ae.join(e,".env.example"),`
1834
- `+o);let a={ai:"latest"},{providerIds:c,customEndpoint:i}=t;(c.includes("openai")||i||c.some(m=>en.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=Ae.join(e,"package.json");if(W.existsSync(d)){let m=JSON.parse(await W.promises.readFile(d,"utf-8"));m.dependencies||(m.dependencies={});for(let[S,me]of Object.entries(a))m.dependencies[S]=me;await W.promises.writeFile(d,JSON.stringify(m,null,2)+`
1835
- `)}}import u from"fs";import E from"path";function rn(e,t){if(!u.existsSync(e))return;let n=u.readdirSync(e);for(let r of n){let o=E.join(e,r);u.statSync(o).isDirectory()?rn(o,t):t(o)}}async function on(e,t){let n=E.join(e,"package.json");if(!u.existsSync(n))return;let r=JSON.parse(u.readFileSync(n,"utf8"));if(t.orm!=="prisma"){let o=E.join(e,"packages","db");if(u.existsSync(o)){let s=E.join(o,"prisma");u.existsSync(s)&&u.rmSync(s,{recursive:!0,force:!0});let a=E.join(o,"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)+`
1836
- `)}let c=E.join(o,"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,`
1837
1864
  export const prisma = {} as any;
1838
1865
  export const db = {} as any;
1839
1866
  export type PrismaClient = any;
@@ -1879,7 +1906,7 @@ export type UsageAggregate = any;
1879
1906
  export type UsageLedgerEntry = any;
1880
1907
  export type UsageType = any;
1881
1908
  export type UsageLedgerSource = any;
1882
- `)}r.scripts?.postinstall&&(r.scripts.postinstall=r.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let o=E.join(e,"apps");if(u.existsSync(o)){let s=u.readdirSync(o);for(let a of s){let c=E.join(o,a);if(!u.statSync(c).isDirectory())continue;let i=E.join(c,"src","app");if(!u.existsSync(i))continue;["[lang]","[locale]"].forEach(f=>{let p=E.join(i,f);if(u.existsSync(p)){let b=u.readdirSync(p);for(let Fe of b)u.renameSync(E.join(p,Fe),E.join(i,Fe));u.rmdirSync(p)}}),["src/middleware.ts","middleware.ts"].forEach(f=>{let p=E.join(c,f);u.existsSync(p)&&u.rmSync(p)});let d=E.join(c,"src","lib");u.existsSync(d)||u.mkdirSync(d,{recursive:!0});let m=E.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,`
1883
1910
  import React from 'react';
1884
1911
  export function useTranslations(namespace?: string): any { return (key: string) => key; }
1885
1912
  export function useLocale() { return 'en'; }
@@ -1897,7 +1924,7 @@ export const useRouter = () => ({ push: (...args: any[]) => {}, replace: (...arg
1897
1924
  export default function createMiddleware(...args: any[]) { return (req: any) => req; }
1898
1925
  export function createNavigation(...args: any[]) { return { Link, redirect, usePathname, useRouter, getPathname: () => '/' }; }
1899
1926
  export function defineRouting<T>(config: T): T { return config; }
1900
- `);let me=E.join(d,"mock-i18n.d.ts");u.writeFileSync(me,`declare module '@/lib/mock-i18n' {
1927
+ `);let U=v.join(d,"mock-i18n.d.ts");g.writeFileSync(U,`declare module '@/lib/mock-i18n' {
1901
1928
  export function useTranslations(namespace?: string): any;
1902
1929
  export function useLocale(): string;
1903
1930
  export const NextIntlClientProvider: React.FC<any>;
@@ -1915,14 +1942,18 @@ export function defineRouting<T>(config: T): T { return config; }
1915
1942
  export function createNavigation(...args: any[]): any;
1916
1943
  export function defineRouting<T>(config: T): T;
1917
1944
  }
1918
- `),u.writeFileSync(E.join(d,"mock-i18n-index.ts"),`
1945
+ `),g.writeFileSync(v.join(d,"mock-i18n-index.ts"),`
1919
1946
  export * from './mock-i18n';
1920
1947
  export { default } from './mock-i18n';
1921
- `);let ge=E.join(c,"tsconfig.json");if(u.existsSync(ge))try{let f=u.readFileSync(ge,"utf8");if(f.includes('"paths": {')){let p=f.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": {
1922
1949
  "next-intl": ["./src/lib/mock-i18n"],
1923
- "next-intl/*": ["./src/lib/mock-i18n"],`);u.writeFileSync(ge,p)}}catch{}let Ce=E.join(c,"src");u.existsSync(Ce)&&rn(Ce,f=>{if(!f.endsWith(".ts")&&!f.endsWith(".tsx"))return;let p=u.readFileSync(f,"utf8"),b=!1;f.endsWith("src/app/layout.tsx")&&p.includes("../providers")&&(p=p.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),b=!0),p=p.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),p=p.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),p.match(/locale\s*:\s*any/)&&(p=p.replace(/locale\s*:\s*any/g,"locale: string"),b=!0),p.match(/lang\s*:\s*any/)&&(p=p.replace(/lang\s*:\s*any/g,"lang: string"),b=!0),p.match(/requestLocale\s*:\s*any/)&&(p=p.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),b=!0),p.match(/\(locale\s*=\s*(.*)\)/)&&(p=p.replace(/\(locale\s*=\s*(.*)\)/g,"() "),b=!0),p.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(p=p.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),(f.endsWith("src/app/layout.tsx")||f.endsWith("src/app/sitemap.ts")||f.endsWith("src/app/robots.ts")||f.endsWith("src/components/ui/locale-switcher.tsx")||f.endsWith("src/app/(marketing)/blog/[slug]/page.tsx"))&&(p=p.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),p=p.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),p=p.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),p=p.replace(/\(l\)\s*=>/g,"(l: any) =>"),b=!0),f.endsWith("src/i18n/request.ts")&&(p=p.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),b=!0),(p.match(/locale\s*:/)||p.match(/lang\s*:/))&&(b=!0),b&&u.writeFileSync(f,p)});let we=E.join(c,"package.json");if(u.existsSync(we)){let f=JSON.parse(u.readFileSync(we,"utf8"));f.dependencies&&delete f.dependencies["next-intl"],u.writeFileSync(we,JSON.stringify(f,null,2)+`
1924
- `)}}}}u.writeFileSync(n,JSON.stringify(r,null,2)+`
1925
- `)}import X from"fs";import ae from"path";function bo(e){let t=[ae.join(e,"packages","db"),ae.join(e,"apps","web")];for(let n of t){let r=ae.join(n,"prisma","schema.prisma");if(X.existsSync(r))return{packageDir:n,seedPath:ae.join(n,"prisma","seed.ts"),packageJsonPath:ae.join(n,"package.json")}}return null}function Ao(e){try{let t=X.readFileSync(e,"utf8"),n=new Set,r=/^\s*model\s+(\w+)\s*\{/gm,o=r.exec(t);for(;o;)n.add(o[1]),o=r.exec(t);return n}catch{return new Set}}function Co(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 {
1926
1957
  const admin = await prisma.user.create({
1927
1958
  data: {
1928
1959
  clerkId: "user_mock_admin",
@@ -1953,7 +1984,7 @@ export { default } from './mock-i18n';
1953
1984
  console.log("\\u2713 Created admin user:", admin.email);
1954
1985
  } catch (err) {
1955
1986
  console.warn("\\u26A0 Admin user creation skipped:", (err as Error).message);
1956
- }`}function wo(e,t){let n=t.has("Tenant"),r=t.has("User"),o=t.has("Project"),s=Co(e,r),a=n?` 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 }> = [];
1957
1988
  try {
1958
1989
  tenants = await Promise.all([
1959
1990
  prisma.tenant.create({
@@ -1970,7 +2001,7 @@ export { default } from './mock-i18n';
1970
2001
  } catch (err) {
1971
2002
  console.warn("\\u26A0 Tenant creation skipped:", (err as Error).message);
1972
2003
  }`:` const tenants: Array<{ id: string; name: string }> = [];
1973
- console.log("\\u2139 No Tenant model in schema \u2014 skipping tenant seed.");`,c=o&&n?` for (const tenant of tenants) {
2004
+ console.log("\\u2139 No Tenant model in schema \u2014 skipping tenant seed.");`,c=r&&o?` for (const tenant of tenants) {
1974
2005
  try {
1975
2006
  await prisma.project.createMany({
1976
2007
  data: [
@@ -2022,12 +2053,12 @@ main()
2022
2053
  .finally(async () => {
2023
2054
  await prisma.$disconnect();
2024
2055
  });
2025
- `}function No(e){if(X.existsSync(e))try{let t=X.readFileSync(e,"utf8"),n=JSON.parse(t),r=n.scripts??{},o=!1;r["db:seed"]||(r["db:seed"]="prisma db seed",o=!0);let s=n.prisma??{};if(s.seed||(s.seed="tsx prisma/seed.ts",o=!0),!o)return;let a={...n,scripts:r,prisma:s};X.writeFileSync(e,JSON.stringify(a,null,2)+`
2026
- `)}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`[create-sailor] Failed to patch seed scripts in ${e}: ${n}`)}}async function sn(e,t){let n=bo(e);if(n)try{let r=ae.join(n.packageDir,"prisma","schema.prisma"),o=Ao(r),s=wo(t,o),a=ae.dirname(n.seedPath);X.existsSync(a)||X.mkdirSync(a,{recursive:!0}),X.writeFileSync(n.seedPath,s),No(n.packageJsonPath)}catch(r){let o=r instanceof Error?r.message:String(r);throw console.error(`[create-sailor] Failed to generate seed data: ${o}`),new Error(`Unable to write prisma/seed.ts: ${o}`)}}import H from"fs";import ce from"path";var He=[{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:""}],ji=He.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function an(e){return He.find(t=>t.id===e)}var To="@nebutra/sms",xo={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 at(e,t){H.mkdirSync(ce.dirname(e),{recursive:!0}),H.writeFileSync(e,t)}function Ro(e,t){let n=ce.join(e,".env.example");H.existsSync(n)?H.appendFileSync(n,`
2027
- `+t):H.writeFileSync(n,t)}function ko(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,n=e.envVars.map(r=>`${r}=`).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(`
2028
2059
  `);return`${t}
2029
- ${n}
2030
- `}var Oo=`/**
2060
+ ${o}
2061
+ `}var mi=`/**
2031
2062
  * Inputs for the \`sendSms\` wrapper. Keep this surface portable across
2032
2063
  * providers \u2014 provider-specific options belong in the wrapper itself.
2033
2064
  */
@@ -2047,7 +2078,7 @@ export interface SendSmsResult {
2047
2078
  provider: string;
2048
2079
  raw?: unknown;
2049
2080
  }
2050
- `;function Uo(){return`import twilio from "twilio";
2081
+ `;function gi(){return`import twilio from "twilio";
2051
2082
  import type { SendSmsInput, SendSmsResult } from "./types.js";
2052
2083
 
2053
2084
  let client: ReturnType<typeof twilio> | null = null;
@@ -2082,7 +2113,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2082
2113
  }
2083
2114
 
2084
2115
  export type { SendSmsInput, SendSmsResult } from "./types.js";
2085
- `}function Lo(){return`import messagebird from "messagebird";
2116
+ `}function fi(){return`import messagebird from "messagebird";
2086
2117
  import type { SendSmsInput, SendSmsResult } from "./types.js";
2087
2118
 
2088
2119
  let client: ReturnType<typeof messagebird> | null = null;
@@ -2120,7 +2151,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2120
2151
  }
2121
2152
 
2122
2153
  export type { SendSmsInput, SendSmsResult } from "./types.js";
2123
- `}function Mo(){return`import plivo from "plivo";
2154
+ `}function yi(){return`import plivo from "plivo";
2124
2155
  import type { SendSmsInput, SendSmsResult } from "./types.js";
2125
2156
 
2126
2157
  let client: InstanceType<typeof plivo.Client> | null = null;
@@ -2159,7 +2190,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2159
2190
  }
2160
2191
 
2161
2192
  export type { SendSmsInput, SendSmsResult } from "./types.js";
2162
- `}function jo(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2193
+ `}function Si(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2163
2194
  import * as $OpenApi from "@alicloud/openapi-client";
2164
2195
  import type { SendSmsInput, SendSmsResult } from "./types.js";
2165
2196
 
@@ -2208,7 +2239,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2208
2239
  }
2209
2240
 
2210
2241
  export type { SendSmsInput, SendSmsResult } from "./types.js";
2211
- `}function Do(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2242
+ `}function Ei(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2212
2243
  import type { SendSmsInput, SendSmsResult } from "./types.js";
2213
2244
 
2214
2245
  const SmsClient = tencentcloud.sms.v20210111.Client;
@@ -2273,7 +2304,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2273
2304
  }
2274
2305
 
2275
2306
  export type { SendSmsInput, SendSmsResult } from "./types.js";
2276
- `}function Fo(){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
2277
2308
  import Yunpian from "yunpian-nodejs-sdk";
2278
2309
  import type { SendSmsInput, SendSmsResult } from "./types.js";
2279
2310
 
@@ -2325,13 +2356,13 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2325
2356
  }
2326
2357
 
2327
2358
  export type { SendSmsInput, SendSmsResult } from "./types.js";
2328
- `}function Bo(e){switch(e){case"twilio":return Uo();case"messagebird":return Lo();case"plivo":return Mo();case"aliyun-sms":return jo();case"tencent-sms":return Do();case"yunpian":return Fo();case"none":return`export {};
2329
- `}}function Yo(e){let t={};for(let r of e.pkgs??[]){let o=xo[r];o&&(t[r]=o)}let n={name:To,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(n,null,2)+`
2330
- `}async function cn(e,t,n="global"){if(t==="none")return;let r=an(t);if(!r)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${He.map(a=>a.id).join(", ")}`);let o=ce.join(e,"packages","sms");if(!H.existsSync(o))return;let s=ce.join(o,"src");H.existsSync(s)&&H.rmSync(s,{recursive:!0,force:!0});try{at(ce.join(o,"package.json"),Yo(r)),at(ce.join(s,"types.ts"),Oo),at(ce.join(s,"index.ts"),Bo(r.id)),Ro(e,ko(r))}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 le from"fs";import pe from"path";var ze=[{id:"r2",name:"Cloudflare R2",region:"global",envVars:["R2_ACCOUNT_ID","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY","R2_BUCKET"],docs:"https://developers.cloudflare.com/r2/api/s3/api/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"s3",name:"AWS S3",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_S3_REGION","S3_BUCKET"],docs:"https://docs.aws.amazon.com/s3/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"supabase-storage",name:"Supabase Storage",region:"global",envVars:["SUPABASE_URL","SUPABASE_SERVICE_ROLE_KEY","SUPABASE_BUCKET"],docs:"https://supabase.com/docs/guides/storage",pkg:"@supabase/supabase-js",pkgVersion:"^2.45.4"},{id:"aliyun-oss",name:"\u963F\u91CC\u4E91 OSS",region:"cn",envVars:["ALIYUN_OSS_ACCESS_KEY","ALIYUN_OSS_ACCESS_SECRET","ALIYUN_OSS_REGION","ALIYUN_OSS_BUCKET"],docs:"https://help.aliyun.com/product/31815.html",pkg:"ali-oss",pkgVersion:"^6.21.0"},{id:"tencent-cos",name:"\u817E\u8BAF\u4E91 COS",region:"cn",envVars:["TENCENT_COS_SECRET_ID","TENCENT_COS_SECRET_KEY","TENCENT_COS_BUCKET","TENCENT_COS_REGION"],docs:"https://cloud.tencent.com/document/product/436",pkg:"cos-nodejs-sdk-v5",pkgVersion:"^2.13.7"},{id:"qiniu",name:"\u4E03\u725B\u4E91 Kodo",region:"cn",envVars:["QINIU_ACCESS_KEY","QINIU_SECRET_KEY","QINIU_BUCKET","QINIU_DOMAIN"],docs:"https://developer.qiniu.com/kodo",pkg:"qiniu",pkgVersion:"^7.14.0"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function pn(e){return ze.find(t=>t.id===e)}var Vi=ze.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var de="@nebutra/storage";function ct(e,t){le.mkdirSync(pe.dirname(e),{recursive:!0}),le.writeFileSync(e,t)}function Ko(e,t){let n=pe.join(e,".env.example");le.existsSync(n)?le.appendFileSync(n,`
2331
- `+t):le.writeFileSync(n,t)}function Vo(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,n=e.envVars.map(r=>`${r}=`).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(`
2332
2363
  `);return`${t}
2333
- ${n}
2334
- `}var $o=`/**
2364
+ ${o}
2365
+ `}var Ii=`/**
2335
2366
  * Inputs for the \`uploadFile\` wrapper. Keep this surface portable across
2336
2367
  * providers \u2014 provider-specific options belong in the wrapper itself.
2337
2368
  */
@@ -2357,8 +2388,8 @@ export interface SignedUrlOptions {
2357
2388
  operation?: "get" | "put";
2358
2389
  contentType?: string;
2359
2390
  }
2360
- `;function qo(){return`/**
2361
- * @${de.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.
2362
2393
  *
2363
2394
  * Docs: https://developers.cloudflare.com/r2/api/s3/api/
2364
2395
  */
@@ -2421,8 +2452,8 @@ export async function getSignedUrl(
2421
2452
  }
2422
2453
 
2423
2454
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2424
- `}function Go(){return`/**
2425
- * @${de.slice(1)} \u2014 AWS S3 wrapper.
2455
+ `}function Ai(){return`/**
2456
+ * @${we.slice(1)} \u2014 AWS S3 wrapper.
2426
2457
  *
2427
2458
  * Docs: https://docs.aws.amazon.com/s3/
2428
2459
  */
@@ -2486,8 +2517,8 @@ export async function getSignedUrl(
2486
2517
  }
2487
2518
 
2488
2519
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2489
- `}function Wo(){return`/**
2490
- * @${de.slice(1)} \u2014 Supabase Storage wrapper.
2520
+ `}function wi(){return`/**
2521
+ * @${we.slice(1)} \u2014 Supabase Storage wrapper.
2491
2522
  *
2492
2523
  * Docs: https://supabase.com/docs/guides/storage
2493
2524
  */
@@ -2549,8 +2580,8 @@ export async function getSignedUrl(
2549
2580
  }
2550
2581
 
2551
2582
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2552
- `}function Xo(){return`/**
2553
- * @${de.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.
2554
2585
  *
2555
2586
  * Docs: https://help.aliyun.com/product/31815.html
2556
2587
  */
@@ -2596,8 +2627,8 @@ export async function getSignedUrl(
2596
2627
  }
2597
2628
 
2598
2629
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2599
- `}function Ho(){return`/**
2600
- * @${de.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.
2601
2632
  *
2602
2633
  * Docs: https://cloud.tencent.com/document/product/436
2603
2634
  */
@@ -2651,8 +2682,8 @@ export async function getSignedUrl(
2651
2682
  }
2652
2683
 
2653
2684
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2654
- `}function zo(){return`/**
2655
- * @${de.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2685
+ `}function xi(){return`/**
2686
+ * @${we.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2656
2687
  *
2657
2688
  * Docs: https://developer.qiniu.com/kodo
2658
2689
  */
@@ -2719,9 +2750,9 @@ export async function getSignedUrl(
2719
2750
  }
2720
2751
 
2721
2752
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2722
- `}function Jo(e){switch(e){case"r2":return qo();case"s3":return Go();case"supabase-storage":return Wo();case"aliyun-oss":return Xo();case"tencent-cos":return Ho();case"qiniu":return zo();case"none":return`export {};
2723
- `}}function Qo(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 n={name:de,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(n,null,2)+`
2724
- `}async function ln(e,t,n){if(t==="none")return;let r=pn(t);if(!r)throw new Error(`Unknown storage provider "${t}". Valid ids: ${ze.map(a=>a.id).join(", ")}`);let o=pe.join(e,"packages","storage"),s=pe.join(o,"src");le.existsSync(s)&&le.rmSync(s,{recursive:!0,force:!0}),ct(pe.join(o,"package.json"),Qo(r)),ct(pe.join(s,"types.ts"),$o),ct(pe.join(s,"index.ts"),Jo(r.id)),Ko(e,Vo(r))}import ue from"fs";import De from"path";function Zo(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";
2725
2756
 
2726
2757
  export default function WelcomePage() {
2727
2758
  const projectName = ${JSON.stringify(e)};
@@ -2761,9 +2792,9 @@ export default function WelcomePage() {
2761
2792
  />
2762
2793
  <Step
2763
2794
  number={4}
2764
- title="Customize your brand"
2765
- description="Colors, domain, logo, SEO \u2014 all in one file"
2766
- 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"
2767
2798
  />
2768
2799
  </ol>
2769
2800
  </section>
@@ -2830,7 +2861,7 @@ function Step({
2830
2861
  </li>
2831
2862
  );
2832
2863
  }
2833
- `}function es(e,t){return`# Next steps \u2014 ${e}
2864
+ `}function Ui(e,t){return`# Next steps \u2014 ${e}
2834
2865
 
2835
2866
  Region: ${t}
2836
2867
 
@@ -2849,9 +2880,10 @@ Your AI-native SaaS scaffold is ready. Complete these four steps to go from temp
2849
2880
  pnpm db:seed
2850
2881
  \`\`\`
2851
2882
 
2852
- 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
2853
2884
  \`\`\`bash
2854
- pnpm sailor brand init
2885
+ pnpm brand:init
2886
+ pnpm brand:apply
2855
2887
  \`\`\`
2856
2888
 
2857
2889
  After setup, delete the welcome route at \`apps/web/src/app/[locale]/welcome/\`.
@@ -2861,23 +2893,26 @@ After setup, delete the welcome route at \`apps/web/src/app/[locale]/welcome/\`.
2861
2893
  - [Documentation](/docs)
2862
2894
  - [GitHub](https://github.com/nebutra/nebutra-sailor)
2863
2895
  - [Get free license (Individual/OPC)](https://nebutra.com/get-license)
2864
- `}async function dn(e,t){let{projectName:n,region:r}=t;try{let o=De.join(e,".sailor");ue.existsSync(o)||ue.mkdirSync(o,{recursive:!0}),ue.writeFileSync(De.join(o,"next-steps.md"),es(n,r))}catch(o){let s=o instanceof Error?o.message:String(o);console.warn(`[create-sailor] Failed to write .sailor/next-steps.md: ${s}`)}try{let o=De.join(e,"apps","web");if(!ue.existsSync(o))return;let s=De.join(o,"src","app","[locale]","welcome");ue.existsSync(s)||ue.mkdirSync(s,{recursive:!0}),ue.writeFileSync(De.join(s,"page.tsx"),Zo(n))}catch(o){let s=o instanceof Error?o.message:String(o);console.warn(`[create-sailor] Failed to write welcome page: ${s}`)}}var mn="create-sailor";function l(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2865
- `)}function rs(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function gn(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 fn(e){return e==="drizzle"?"drizzle":e==="none"?"none":"prisma"}function yn(e){return e==="lemon"||e==="lemonsqueezy"?"lemonsqueezy":e==="none"?"none":"stripe"}function Sn(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 En(e){if(!e)return"clerk";let t=e.toLowerCase();return t==="betterauth"||t==="better-auth"?"betterauth":t==="none"?"none":"clerk"}function hn(e){if(!e)return["openai"];let t=e.split(",").map(n=>n.trim().toLowerCase());return t.includes("none")?[]:t}var _n={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function vn(e,t){if(!e)return"fumadocs";let n=e.toLowerCase();if(n==="fumadocs"||n==="none")return n;if(n in _n){let r=_n[n];return t?l(!0,{event:"notice",kind:"docs-fallback",requested:n,effective:"fumadocs"}):process.stdout.write(T.yellow(`\u26A0 ${r} support is coming in v1.2. Falling back to fumadocs.
2866
- `)+T.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
2867
- `)),"fumadocs"}return"fumadocs"}function In(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 Pn(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function os(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"}}function bn(e){return e==="cn"?"wechat":"stripe"}async function ss(){let e=new ts;e.name(mn).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(J,"-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("--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(),[n]=e.args;t.help&&(gt(),process.exit(0));let r=!!t.json,o=!!t.dryRun,s=!!t.yes,a=s||!process.stdin.isTTY;r||ut(),l(r,{event:"start",version:J});let c=n??(s?"./my-saas-app":void 0),i;if(c)i=c;else if(a)i="./my-saas-app";else{let g=await I.group({name:()=>I.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(T.red(`\u2718 Cancelled
2868
- `)),process.exit(130)}});i=String(g.name)}let d=pt.basename(pt.resolve(i)),m=t.pm??rs(),S=!!t.region,me=!!t.auth,ge=!!t.payment,Ce=!!t.ai,we=!!t.email,f=!!t.storage,p=!!t.monitoring,b=!!t.analytics,Fe=!!t.sms,lt=t.i18n!==void 0,h,Ne,Y,Qe,V,O,U=bt(t.socialLogin),z,fe,$,x,Be;if(a){h=Pn(t.region),Ne=fn(t.orm),Y=gn(t.db);let g=ge?t.payment:bn(h);Qe=yn(g),V=Sn(g),O=En(t.auth),z=hn(t.ai),$=In(t.deploy),x=vn(t.docs,r),Be=lt?!!t.i18n:!0}else{let g={};if(S||(g.region=()=>I.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"})),me||(g.auth=()=>I.select({message:"Auth provider?",options:[{value:"clerk",label:"Clerk"},{value:"betterauth",label:"Better Auth"},{value:"none",label:"None"}],initialValue:"clerk"})),!Ce){let Ve=Array.from(new Set(Ge.map(_=>_.category)));g.aiCategories=()=>I.multiselect({message:"Which AI Provider categories do you want to explore? (Select multiple)",options:Ve.map(_=>({value:_,label:_})),initialValues:["\u76F4\u63A5\u5B9E\u9A8C\u5BA4","\u7EDF\u4E00\u7F51\u5173"]}),g.aiProviders=({results:_})=>{let L=_.aiCategories||[],$e=Ge.filter(xe=>L.includes(xe.category)).map(xe=>({value:xe.id,label:`[${xe.category}] ${xe.name}`}));return $e.push({value:"custom",label:"[\u81EA\u5B9A\u4E49] Custom OpenAI-compatible endpoint"}),I.multiselect({message:"Select AI Providers (Space to select, Enter to submit)",options:$e,initialValues:["openai","anthropic"],required:!1})},g.enableCustom=({results:_})=>_.aiProviders?.includes("custom")?I.confirm({message:"Configure custom OpenAI-compatible endpoint?",initialValue:!0}):Promise.resolve(!1),g.customAiName=({results:_})=>_.enableCustom?I.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),g.customAiBaseUrl=({results:_})=>_.enableCustom?I.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:L=>{if(L.length===0)return"Base URL is required."}}):Promise.resolve(void 0),g.customAiApiKeyEnv=({results:_})=>_.enableCustom?I.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(g).length>0?await I.group(g,{onCancel:()=>{process.stdout.write(T.red(`\u2718 Cancelled
2869
- `)),process.exit(130)}}):{};h=Pn(S?t.region:y.region),Ne=fn(t.orm),Y=gn(t.db);let R=ge?t.payment:bn(h);Qe=yn(R),V=Sn(R),O=En(me?t.auth:y.auth),z=Ce?hn(t.ai):y.aiProviders?.filter(Ve=>Ve!=="custom")??[],y.enableCustom&&(fe={name:y.customAiName,baseURL:y.customAiBaseUrl,apiKeyEnvName:y.customAiApiKeyEnv}),$=In(t.deploy),x=vn(t.docs,r),Be=lt?!!t.i18n:!0}let Te=os(h),ye=we?t.email:Te.email,Se=f?t.storage:Te.storage,Ee=p?t.monitoring:Te.monitoring,he=b?t.analytics:Te.analytics,_e=Fe?t.sms:Te.sms,Ye={region:h,orm:Ne,database:Y,payment:Qe,aiProviders:z,customAiEndpoint:fe,deployTarget:$,docs:x,i18n:Be,email:ye,storage:Se,monitoring:Ee,analytics:he,sms:_e},Ke=[["Project name",d],["Region",h],["Auth",O],["Social login",U.length>0?U.map(g=>Re.find(y=>y.id===g)?.name??g).join(", "):"none"],["ORM",Ne],["Database",Y],["Payment",V],["AI",Array.isArray(z)?z.join(", ")+(fe?", custom":""):String(z)],["Email",ye],["Storage",Se],["Monitoring",Ee],["Analytics",he],["SMS",_e],["Deploy Target",$],["Docs Framework",x]];r?Ke.forEach(([g,y],R)=>{l(!0,{event:"step",step:g,value:y,index:R+1,total:Ke.length})}):Ke.forEach(([g,y],R)=>{yt({index:R+1,total:Ke.length,label:g,value:y})});let An={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""},Cn=Date.now();if(o){let g=z.length,y=[`clone template \u2192 ${i}`,"write nebutra.config.json",`prune template (orm=${Ne}, i18n=${Be})`,`region \u2192 ${h}`,`auth \u2192 ${O==="none"?"skip (remove packages/auth)":`configure ${O}`}`,...U.length>0?[`social-login \u2192 generate ${U.length} callback route${U.length===1?"":"s"} + SocialLoginButtons.tsx (${U.join(", ")})`]:[],`db \u2192 ${Y==="none"?"skip (remove packages/db)":`configure Prisma for ${Y}`}`,`payment \u2192 ${V==="none"?"skip (remove packages/billing)":`configure ${V}`}`,...x!=="none"?[`docs \u2192 scaffold apps/docs (${x==="fumadocs"?"fumadocs":`${x} \u2192 fumadocs fallback`})`]:[],...g>0||fe?[`ai-providers \u2192 generate registry.ts + env (${g}${fe?" + custom":""} provider${g===1&&!fe?"":"s"})`]:[],...ye!=="none"?[`email \u2192 configure ${ye}`]:[],...Se!=="none"?[`storage \u2192 configure ${Se}`]:[],...Ee!=="none"?[`monitoring \u2192 configure ${Ee}`]:[],...he!=="none"?[`analytics \u2192 configure ${he}`]:[],..._e!=="none"?[`sms \u2192 configure ${_e}`]:[],`compliance \u2192 inject ${h} boilerplate (ICP/Cookie/AIGC/Privacy)`,"welcome \u2192 generate dev welcome page","env \u2192 generate random secrets (AUTH_SECRET, JWT_SECRET)","seed \u2192 generate prisma/seed.ts (1 admin + 3 tenants)",...$!=="none"?[`deploy \u2192 inject ${$} config`]:[],"inject .env.local",t.install===!1?"skip install":`run ${m} install`,t.git===!1?"skip git init":"run git init"];if(r)y.forEach(R=>l(!0,{event:"plan",action:R})),l(!0,{event:"done",dryRun:!0});else{process.stdout.write(`
2870
- `+T.bold(`Dry run \u2014 planned actions:
2871
- `));for(let R of y)process.stdout.write(` \u2022 ${R}
2872
- `);process.stdout.write(T.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(`
2873
2908
  No files were written.
2874
- `))}process.exit(0)}let wn=async()=>{process.stdout.write(`
2875
- `+T.red(`\u2718 Cancelled
2876
- `)),un.existsSync(i)&&await I.confirm({message:`Cleanup partial install at ${i}?`,initialValue:!0})===!0&&(un.rmSync(i,{recursive:!0,force:!0}),process.stdout.write(T.dim(` \u2713 Removed ${i}
2877
- `))),process.exit(130)};process.on("SIGINT",wn);try{l(r,{event:"step",step:"clone",status:"start"}),await qt(i),l(r,{event:"step",step:"clone",status:"ok"}),l(r,{event:"step",step:"package",status:"start"}),await Ht(i,d),l(r,{event:"step",step:"package",status:"ok"}),l(r,{event:"step",step:"config",status:"start"}),await Nt(i,Ye),l(r,{event:"step",step:"config",status:"ok"}),l(r,{event:"step",step:"prune",status:"start"}),await on(i,Ye),l(r,{event:"step",step:"prune",status:"ok"}),l(r,{event:"step",step:"auth",choice:O,status:"start"}),await It(i,O),l(r,{event:"step",step:"auth",choice:O,status:"ok"}),U.length>0?(l(r,{event:"step",step:"social-login",providers:U,status:"start"}),await Ct(i,U,O),l(r,{event:"step",step:"social-login",providers:U,status:"ok"})):l(r,{event:"step",step:"social-login",status:"skip"}),l(r,{event:"step",step:"db",choice:Y,status:"start"}),await Rt(i,Y,d),l(r,{event:"step",step:"db",choice:Y,status:"ok"}),l(r,{event:"step",step:"payment",choice:V,status:"start"}),await Jt(i,V),l(r,{event:"step",step:"payment",choice:V,status:"ok"}),await Dt(i,ye,h),r&&l(!0,{event:"step",step:"email",choice:ye,status:"ok"}),await ln(i,Se,h),r&&l(!0,{event:"step",step:"storage",choice:Se,status:"ok"}),await Xt(i,Ee,h),r&&l(!0,{event:"step",step:"monitoring",choice:Ee,status:"ok"}),await ht(i,he,h),r&&l(!0,{event:"step",step:"analytics",choice:he,status:"ok"}),await cn(i,_e,h),r&&l(!0,{event:"step",step:"sms",choice:_e,status:"ok"}),await wt(i,h),r&&l(!0,{event:"step",step:"compliance",region:h,status:"ok"}),await Yt(i),await sn(i,O),await dn(i,{projectName:d,region:h}),l(r,{event:"step",step:"ai-providers",status:"start"});let g={providerIds:Ye.aiProviders,customEndpoint:Ye.customAiEndpoint},y=pt.join(i,"packages/ai-providers/templates");if(await nn(i,g,y),l(r,{event:"step",step:"ai-providers",status:"ok"}),l(r,{event:"step",step:"docs",status:"start"}),x!=="none"?(await Ut(i,{framework:x,projectName:d}),l(r,{event:"step",step:"docs",framework:"fumadocs",requested:x,status:"ok"})):l(r,{event:"step",step:"docs",status:"skip"}),l(r,{event:"step",step:"deploy-target",status:"start"}),$!=="none"&&await kt(i,$),l(r,{event:"step",step:"deploy-target",status:"ok"}),l(r,{event:"step",step:"env",status:"start"}),await Vt(i,An),l(r,{event:"step",step:"env",status:"ok"}),t.install!==!1){let L=m==="bun"?"bun install":`${m} install`;r?l(!0,{event:"step",step:"install",pm:m,status:"start"}):process.stdout.write(T.dim(` Installing dependencies with ${m}\u2026
2878
- `));try{Je(L,{cwd:i,stdio:r?"ignore":"inherit"}),l(r,{event:"step",step:"install",status:"ok"})}catch(ve){let $e=ve instanceof Error?ve.message:String(ve);r?l(!0,{event:"step",step:"install",status:"error",error:$e}):process.stdout.write(T.yellow(` \u26A0 install failed \u2014 run '${L}' manually.
2879
- `))}}else l(r,{event:"step",step:"install",status:"skip"});if(t.git!==!1){r&&l(!0,{event:"step",step:"git-init",status:"start"});try{Je("git init -q",{cwd:i,stdio:"ignore"}),Je("git add -A",{cwd:i,stdio:"ignore"}),Je('git -c user.email=you@example.com -c user.name="You" commit -q -m "chore: initial scaffold from create-sailor"',{cwd:i,stdio:"ignore"}),l(r,{event:"step",step:"git-init",status:"ok"})}catch(L){let ve=L instanceof Error?L.message:String(L);r?l(!0,{event:"step",step:"git-init",status:"error",error:ve}):process.stdout.write(T.yellow(` \u26A0 git init skipped \u2014 not fatal.
2880
- `))}}else l(r,{event:"step",step:"git-init",status:"skip"});let _=Math.max(1,Math.round((Date.now()-Cn)/1e3));r?l(!0,{event:"done",status:"ok",elapsedSec:_,targetDir:i}):mt({elapsedSec:_,targetDir:i,skippedInstall:t.install===!1});try{ns({pkg:{name:mn,version:J},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}process.exit(0)}catch(g){let y=g instanceof Error?g.message:String(g);r?l(!0,{event:"error",message:y}):process.stdout.write(T.red(`
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(`
2881
2916
  \u2718 Failed: ${y}
2882
- `)),process.exit(1)}}ss().catch(e=>{process.stderr.write(String(e)+`
2917
+ `)),process.exit(1)}}ji().catch(e=>{process.stderr.write(String(e)+`
2883
2918
  `),process.exit(1)});