create-sailor 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/index.js +224 -207
  2. package/package.json +2 -1
  3. package/templates/deploy/Dockerfile.web +57 -0
  4. package/templates/deploy/docker-compose.yml +40 -0
  5. package/templates/deploy/railway.toml +13 -0
  6. package/templates/deploy/vercel.json +37 -0
  7. package/templates/deploy/wrangler.toml +8 -0
  8. package/templates/docs/docusaurus/README.md +24 -0
  9. package/templates/docs/docusaurus/docs/getting-started/develop.md +20 -0
  10. package/templates/docs/docusaurus/docs/getting-started/install.md +11 -0
  11. package/templates/docs/docusaurus/docs/intro.md +15 -0
  12. package/templates/docs/docusaurus/docusaurus.config.ts +66 -0
  13. package/templates/docs/docusaurus/package.json +43 -0
  14. package/templates/docs/docusaurus/sidebars.ts +14 -0
  15. package/templates/docs/docusaurus/src/css/custom.css +22 -0
  16. package/templates/docs/docusaurus/tsconfig.json +7 -0
  17. package/templates/docs/fumadocs/README.md +46 -0
  18. package/templates/docs/fumadocs/app/(home)/page.tsx +22 -0
  19. package/templates/docs/fumadocs/app/api/search/route.ts +4 -0
  20. package/templates/docs/fumadocs/app/docs/[[...slug]]/page.tsx +39 -0
  21. package/templates/docs/fumadocs/app/docs/layout.tsx +11 -0
  22. package/templates/docs/fumadocs/app/global.css +10 -0
  23. package/templates/docs/fumadocs/app/layout.tsx +18 -0
  24. package/templates/docs/fumadocs/content/docs/api.mdx +31 -0
  25. package/templates/docs/fumadocs/content/docs/concepts.mdx +19 -0
  26. package/templates/docs/fumadocs/content/docs/getting-started.mdx +56 -0
  27. package/templates/docs/fumadocs/content/docs/index.mdx +17 -0
  28. package/templates/docs/fumadocs/content/docs/meta.json +4 -0
  29. package/templates/docs/fumadocs/lib/source.ts +7 -0
  30. package/templates/docs/fumadocs/next.config.mjs +17 -0
  31. package/templates/docs/fumadocs/package.json +30 -0
  32. package/templates/docs/fumadocs/source.config.ts +17 -0
  33. package/templates/docs/fumadocs/tsconfig.json +25 -0
  34. package/templates/docs/mintlify/README.md +25 -0
  35. package/templates/docs/mintlify/api-reference/introduction.mdx +25 -0
  36. package/templates/docs/mintlify/introduction.mdx +21 -0
  37. package/templates/docs/mintlify/mint.json +37 -0
  38. package/templates/docs/mintlify/package.json +13 -0
  39. package/templates/docs/mintlify/quickstart.mdx +26 -0
  40. package/templates/docs/nextra/README.md +35 -0
  41. package/templates/docs/nextra/app/[[...mdxPath]]/page.tsx +23 -0
  42. package/templates/docs/nextra/app/layout.tsx +36 -0
  43. package/templates/docs/nextra/content/_meta.ts +4 -0
  44. package/templates/docs/nextra/content/getting-started.mdx +35 -0
  45. package/templates/docs/nextra/content/index.mdx +18 -0
  46. package/templates/docs/nextra/mdx-components.tsx +10 -0
  47. package/templates/docs/nextra/next.config.mjs +9 -0
  48. package/templates/docs/nextra/package.json +24 -0
  49. package/templates/docs/nextra/tsconfig.json +21 -0
  50. package/templates/docs/vitepress/.vitepress/config.ts +35 -0
  51. package/templates/docs/vitepress/README.md +23 -0
  52. package/templates/docs/vitepress/guide/getting-started.md +26 -0
  53. package/templates/docs/vitepress/guide/introduction.md +12 -0
  54. package/templates/docs/vitepress/index.md +23 -0
  55. package/templates/docs/vitepress/package.json +17 -0
  56. package/templates/docs/vitepress/tsconfig.json +15 -0
  57. package/dist/index.d.ts +0 -1
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import{execSync as Ut}from"child_process";import ye from"fs";import ft from"path";import*as R from"@clack/prompts";import{Command as Qi}from"commander";import N from"picocolors";import Zi from"update-notifier";import or from"cfonts";import rr from"picocolors";import cn from"fs";import Ft from"path";import{fileURLToPath as tr}from"url";function nr(){try{let t=Ft.dirname(tr(import.meta.url));for(let o=0;o<4;o++){let n=Ft.join(t,"package.json");if(cn.existsSync(n)){let r=cn.readFileSync(n,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=Ft.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var re=nr();function pn(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${re}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
3
- `));return}or.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(rr.dim(` AI-Native SaaS Template \xB7 v${re} \xB7 nebutra.com
2
+ import{execSync as yt}from"child_process";import Se from"fs";import St from"path";import*as k from"@clack/prompts";import{Command as Zs}from"commander";import C from"picocolors";import ea from"update-notifier";import rr from"cfonts";import ir from"picocolors";import ln from"fs";import jt from"path";import{fileURLToPath as nr}from"url";function or(){try{let t=jt.dirname(nr(import.meta.url));for(let o=0;o<4;o++){let n=jt.join(t,"package.json");if(ln.existsSync(n)){let r=ln.readFileSync(n,"utf-8"),i=JSON.parse(r);if(i.name==="create-sailor"&&typeof i.version=="string")return i.version}t=jt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var ie=or();function dn(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${ie}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
3
+ `));return}rr.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(ir.dim(` AI-Native SaaS Template \xB7 v${ie} \xB7 nebutra.com
4
4
 
5
- `))}import P from"picocolors";var sr={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 ir(e){return e?sr[e]??"stable":"stable"}function ze(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function se(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 ln(e){let t=[];for(let{flag:o,provider:n}of e){if(!n||n==="none")continue;let r=ir(n);r!=="stable"&&t.push({flag:o,provider:n,status:r})}return t}function ar(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function dn(e){let t=ar(),o=t?"\u2693":"-",n=t?"\u25B8":"->",r=t?"\u2605":"*",s=t?"\u{1F4E7}":"*",c=["",` ${t?P.bold(`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`):`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`}`,"",` ${t?P.bold("Next:"):"Next:"}`,` ${n} cd ${e.targetDir}`];e.skippedInstall&&c.push(` ${n} pnpm install (if --no-install was set)`),c.push(` ${n} fill in .env.local ${t?P.dim("\u2192 add provider keys before booting apps"):"-> add provider keys before booting apps"}`,` ${n} pnpm db:migrate ${t?P.dim("\u2192 sync Prisma schema"):"-> sync Prisma schema"}`,` ${n} pnpm db:seed ${t?P.dim("\u2192 load example tenants and records"):"-> load example tenants and records"}`,` ${n} pnpm dev ${t?P.dim("\u2192 http://localhost:3000"):"-> http://localhost:3000"}`,"",` ${t?P.bold("Customize:"):"Customize:"}`,` ${n} pnpm brand:init ${t?P.dim("\u2192 create brand.config.ts"):"-> create brand.config.ts"}`,` ${n} pnpm brand:apply ${t?P.dim("\u2192 propagate brand changes"):"-> propagate brand changes"}`,` ${n} pnpm preset:env ${t?P.dim("\u2192 review preset env requirements"):"-> review preset env requirements"}`,"",` ${t?P.bold("Useful scripts:"):"Useful scripts:"}`,` ${n} pnpm infra:up ${t?P.dim("\u2192 start local PostgreSQL/Redis/ClickHouse"):"-> start local PostgreSQL/Redis/ClickHouse"}`,` ${n} pnpm generate:api-types ${t?P.dim("\u2192 refresh shared API client types"):"-> refresh shared API client types"}`,` ${n} pnpm lint ${t?P.dim("\u2192 quick repo sanity check"):"-> quick repo sanity check"}`,` ${n} pnpm audit ${t?P.dim("\u2192 scan deps for known CVEs"):"-> scan deps for known CVEs"}`);let a=e.previewSelections??[];if(a.length>0){let k=t?P.bold(P.yellow("\u26A0 Preview features selected:")):"!! Preview features selected:";c.push("",` ${k}`);for(let x of a){let L=ze(x.status),oe=` ${n} ${x.flag} (${x.provider}) ${L}`;c.push(t?P.yellow(oe):oe)}c.push("",` ${t?P.dim(se("foundation")):se("foundation")}`,` ${t?P.dim("You may need to contribute the provider integration yourself."):"You may need to contribute the provider integration yourself."}`,` ${t?P.dim("See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"):"See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"}`)}let l=e.waveFeatures??{},m=k=>k!==!1,y=[];m(l.apiKeys)&&y.push("Manage API keys at /settings/api-keys"),m(l.auditLog)&&y.push("View audit log at /settings/audit-log"),y.push("Configure webhooks at /settings/webhooks"),m(l.commandPalette)&&y.push("Press Cmd/Ctrl+K to open the command palette"),y.push("Edit notification preferences at /settings/notifications"),y.push("Export your data at /settings/account/export"),l.chinaCompliance&&y.push("China deployments \u2014 see packages/china-compliance/README.md"),c.push("",` ${t?P.bold("What you can do next:"):"What you can do next:"}`);for(let k of y)c.push(` ${n} ${k}`);c.push("",` ${t?P.bold("Ship faster:"):"Ship faster:"}`,` ${r} Star us https://github.com/nebutra/nebutra-sailor`,` ${s} Free license https://nebutra.com/get-license`,""),process.stdout.write(c.join(`
5
+ `))}import P from"picocolors";var sr={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 ar(e){return e?sr[e]??"stable":"stable"}function Je(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function se(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 un(e){let t=[];for(let{flag:o,provider:n}of e){if(!n||n==="none")continue;let r=ar(n);r!=="stable"&&t.push({flag:o,provider:n,status:r})}return t}function cr(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function mn(e){let t=cr(),o=t?"\u2693":"-",n=t?"\u25B8":"->",r=t?"\u2605":"*",i=t?"\u{1F4E7}":"*",c=["",` ${t?P.bold(`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`):`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`}`,"",` ${t?P.bold("Next:"):"Next:"}`,` ${n} cd ${e.targetDir}`];e.skippedInstall&&c.push(` ${n} pnpm install (if --no-install was set)`),c.push(` ${n} fill in .env.local ${t?P.dim("\u2192 add provider keys before booting apps"):"-> add provider keys before booting apps"}`,` ${n} pnpm db:migrate ${t?P.dim("\u2192 sync Prisma schema"):"-> sync Prisma schema"}`,` ${n} pnpm db:seed ${t?P.dim("\u2192 load example tenants and records"):"-> load example tenants and records"}`,` ${n} pnpm dev ${t?P.dim("\u2192 http://localhost:3000"):"-> http://localhost:3000"}`,"",` ${t?P.bold("Customize:"):"Customize:"}`,` ${n} pnpm brand:init ${t?P.dim("\u2192 create brand.config.ts"):"-> create brand.config.ts"}`,` ${n} pnpm brand:apply ${t?P.dim("\u2192 propagate brand changes"):"-> propagate brand changes"}`,` ${n} pnpm preset:env ${t?P.dim("\u2192 review preset env requirements"):"-> review preset env requirements"}`,"",` ${t?P.bold("Useful scripts:"):"Useful scripts:"}`,` ${n} pnpm infra:up ${t?P.dim("\u2192 start local PostgreSQL/Redis/ClickHouse"):"-> start local PostgreSQL/Redis/ClickHouse"}`,` ${n} pnpm generate:api-types ${t?P.dim("\u2192 refresh shared API client types"):"-> refresh shared API client types"}`,` ${n} pnpm lint ${t?P.dim("\u2192 quick repo sanity check"):"-> quick repo sanity check"}`,` ${n} pnpm audit ${t?P.dim("\u2192 scan deps for known CVEs"):"-> scan deps for known CVEs"}`);let a=e.previewSelections??[];if(a.length>0){let x=t?P.bold(P.yellow("\u26A0 Preview features selected:")):"!! Preview features selected:";c.push("",` ${x}`);for(let N of a){let L=Je(N.status),re=` ${n} ${N.flag} (${N.provider}) ${L}`;c.push(t?P.yellow(re):re)}c.push("",` ${t?P.dim(se("foundation")):se("foundation")}`,` ${t?P.dim("You may need to contribute the provider integration yourself."):"You may need to contribute the provider integration yourself."}`,` ${t?P.dim("See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"):"See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"}`)}let l=e.waveFeatures??{},m=x=>x!==!1,y=[];m(l.apiKeys)&&y.push("Manage API keys at /settings/api-keys"),m(l.auditLog)&&y.push("View audit log at /settings/audit-log"),y.push("Configure webhooks at /settings/webhooks"),m(l.commandPalette)&&y.push("Press Cmd/Ctrl+K to open the command palette"),y.push("Edit notification preferences at /settings/notifications"),y.push("Export your data at /settings/account/export"),l.chinaCompliance&&y.push("China deployments \u2014 see packages/ops/china-compliance/README.md"),c.push("",` ${t?P.bold("What you can do next:"):"What you can do next:"}`);for(let x of y)c.push(` ${n} ${x}`);c.push("",` ${t?P.bold("Ship faster:"):"Ship faster:"}`,` ${r} Star us https://github.com/nebutra/nebutra-sailor`,` ${i} Free license https://nebutra.com/get-license`,""),process.stdout.write(c.join(`
6
6
  `)+`
7
- `)}var cr=`Usage: create-sailor [name] [options]
7
+ `)}var pr=`Usage: create-sailor [name] [options]
8
8
 
9
9
  Arguments:
10
10
  name project directory (default: ./my-saas-app)
@@ -73,9 +73,9 @@ Examples:
73
73
  $ npx create-sailor@latest my-app --region=cn --auth=clerk
74
74
  $ npx create-sailor@latest my-app --region=hybrid --ai=openai,deepseek
75
75
  $ npm create sailor@latest --dry-run --region=cn
76
- `;function un(){process.stdout.write(cr)}import _t from"picocolors";function mn(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function pr(e){let t=mn()?"\u25B8":"->",o=`[${e.index}/${e.total}]`,n=e.label.padEnd(18," ");return mn()?`${_t.dim(o)} ${_t.bold(n)} ${_t.dim(t)} ${_t.cyan(e.value)}`:`${o} ${n} ${t} ${e.value}`}function gn(e){process.stdout.write(pr(e)+`
77
- `)}var Dt=[{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:[]}],Ea=Dt.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var lr=["openai","anthropic","google"],dr=["openai"];function Kt(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let o=t.length>0?t:[...lr];return{mode:"gateway",providerIds:o,customEndpoint:e.customEndpoint,routing:{profile:"multi-provider-gateway",providerSeed:o,runtimeGovernance:!0}}}case"direct":{let o=t.length>0?t:[...dr];return{mode:"direct",providerIds:o,customEndpoint:e.customEndpoint,routing:{profile:"direct-adapters",providerSeed:o,runtimeGovernance:!1}}}case"custom":return{mode:"custom",providerIds:t,customEndpoint:e.customEndpoint,routing:{profile:"openai-compatible",providerSeed:t,runtimeGovernance:!0}};case"none":return{mode:"none",providerIds:[],routing:{profile:"disabled",providerSeed:[],runtimeGovernance:!1}}}}import Je from"fs";import j from"path";var fn=[{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:""}],ba=fn.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function yn(e){return fn.find(t=>t.id===e)}function ur(e){Je.mkdirSync(e,{recursive:!0})}function G(e,t){ur(j.dirname(e)),Je.writeFileSync(e,t)}function Ee(e,t){let o=j.join(e,".env.example");Je.existsSync(o)?Je.appendFileSync(o,`
78
- `+t):Je.writeFileSync(o,t)}function mr(e){let t=`"use client";
76
+ `;function gn(){process.stdout.write(pr)}import Pt from"picocolors";function fn(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function lr(e){let t=fn()?"\u25B8":"->",o=`[${e.index}/${e.total}]`,n=e.label.padEnd(18," ");return fn()?`${Pt.dim(o)} ${Pt.bold(n)} ${Pt.dim(t)} ${Pt.cyan(e.value)}`:`${o} ${n} ${t} ${e.value}`}function yn(e){process.stdout.write(lr(e)+`
77
+ `)}var Kt=[{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:[]}],va=Kt.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var dr=["openai","anthropic","google"],ur=["openai"];function Vt(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let o=t.length>0?t:[...dr];return{mode:"gateway",providerIds:o,customEndpoint:e.customEndpoint,routing:{profile:"multi-provider-gateway",providerSeed:o,runtimeGovernance:!0}}}case"direct":{let o=t.length>0?t:[...ur];return{mode:"direct",providerIds:o,customEndpoint:e.customEndpoint,routing:{profile:"direct-adapters",providerSeed:o,runtimeGovernance:!1}}}case"custom":return{mode:"custom",providerIds:t,customEndpoint:e.customEndpoint,routing:{profile:"openai-compatible",providerSeed:t,runtimeGovernance:!0}};case"none":return{mode:"none",providerIds:[],routing:{profile:"disabled",providerSeed:[],runtimeGovernance:!1}}}}import Qe from"fs";import F from"path";var Sn=[{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:""}],Pa=Sn.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function hn(e){return Sn.find(t=>t.id===e)}function mr(e){Qe.mkdirSync(e,{recursive:!0})}function W(e,t){mr(F.dirname(e)),Qe.writeFileSync(e,t)}function ve(e,t){let o=F.join(e,".env.example");Qe.existsSync(o)?Qe.appendFileSync(o,`
78
+ `+t):Qe.writeFileSync(o,t)}function gr(e){let t=`"use client";
79
79
  /**
80
80
  * PostHog browser SDK \u2014 lazy-initialized on first access.
81
81
  */
@@ -158,11 +158,11 @@ export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
158
158
 
159
159
  return <>{children}</>;
160
160
  }
161
- `;G(j.join(e,"src","lib","analytics","posthog.client.ts"),t),G(j.join(e,"src","lib","analytics","posthog.server.ts"),o),G(j.join(e,"src","components","analytics","AnalyticsProvider.tsx"),n)}function gr(){return`# PostHog \u2014 product analytics
161
+ `;W(F.join(e,"src","lib","analytics","posthog.client.ts"),t),W(F.join(e,"src","lib","analytics","posthog.server.ts"),o),W(F.join(e,"src","components","analytics","AnalyticsProvider.tsx"),n)}function fr(){return`# PostHog \u2014 product analytics
162
162
  POSTHOG_KEY=
163
163
  NEXT_PUBLIC_POSTHOG_KEY=
164
164
  NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
165
- `}function fr(e){G(j.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
165
+ `}function yr(e){W(F.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
166
166
  /**
167
167
  * Plausible script tag \u2014 lightweight, privacy-friendly analytics.
168
168
  */
@@ -182,10 +182,10 @@ export function PlausibleScript() {
182
182
  />
183
183
  );
184
184
  }
185
- `)}function yr(){return`# Plausible \u2014 privacy-friendly analytics
185
+ `)}function Sr(){return`# Plausible \u2014 privacy-friendly analytics
186
186
  NEXT_PUBLIC_PLAUSIBLE_DOMAIN=
187
187
  NEXT_PUBLIC_PLAUSIBLE_SRC=https://plausible.io/js/script.js
188
- `}function Sr(e){G(j.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
188
+ `}function hr(e){W(F.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
189
189
  /**
190
190
  * Umami analytics \u2014 self-hosted OR umami.is cloud.
191
191
  */
@@ -205,10 +205,10 @@ export function UmamiScript() {
205
205
  />
206
206
  );
207
207
  }
208
- `)}function hr(){return`# Umami \u2014 self-hostable analytics
208
+ `)}function Er(){return`# Umami \u2014 self-hostable analytics
209
209
  NEXT_PUBLIC_UMAMI_WEBSITE_ID=
210
210
  NEXT_PUBLIC_UMAMI_SRC=https://cloud.umami.is/script.js
211
- `}function Er(e){let t=`"use client";
211
+ `}function vr(e){let t=`"use client";
212
212
  import mixpanel from "mixpanel-browser";
213
213
 
214
214
  let initialized = false;
@@ -247,10 +247,10 @@ export function trackServer(
247
247
  if (!c) return;
248
248
  c.track(event, { distinct_id: distinctId, ...properties });
249
249
  }
250
- `;G(j.join(e,"src","lib","analytics","mixpanel.client.ts"),t),G(j.join(e,"src","lib","analytics","mixpanel.server.ts"),o)}function vr(){return`# Mixpanel \u2014 product analytics
250
+ `;W(F.join(e,"src","lib","analytics","mixpanel.client.ts"),t),W(F.join(e,"src","lib","analytics","mixpanel.server.ts"),o)}function _r(){return`# Mixpanel \u2014 product analytics
251
251
  MIXPANEL_TOKEN=
252
252
  NEXT_PUBLIC_MIXPANEL_TOKEN=
253
- `}function _r(e){G(j.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
253
+ `}function br(e){W(F.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
254
254
  /**
255
255
  * \u767E\u5EA6\u7EDF\u8BA1 Baidu Tongji \u2014 hm.js \u57CB\u70B9\u811A\u672C.
256
256
  */
@@ -276,9 +276,9 @@ var _hmt = _hmt || [];
276
276
  />
277
277
  );
278
278
  }
279
- `)}function br(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
279
+ `)}function Pr(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
280
280
  NEXT_PUBLIC_BAIDU_STATS_ID=
281
- `}function Pr(e){G(j.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
281
+ `}function Cr(e){W(F.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
282
282
  /**
283
283
  * \u795E\u7B56\u5206\u6790 (Sensors Analytics) \u2014 sa-sdk-javascript \u5C01\u88C5.
284
284
  */
@@ -306,10 +306,10 @@ export function initSensors(): void {
306
306
  }
307
307
 
308
308
  export { sensors };
309
- `)}function Cr(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
309
+ `)}function Ir(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
310
310
  NEXT_PUBLIC_SENSORS_SERVER_URL=
311
311
  NEXT_PUBLIC_SENSORS_APP_JS_URL=
312
- `}function Ir(e){G(j.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
312
+ `}function Ar(e){W(F.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
313
313
  /**
314
314
  * GrowingIO CDP \u2014 inline snippet installer.
315
315
  */
@@ -334,21 +334,29 @@ gdp("send");
334
334
  />
335
335
  );
336
336
  }
337
- `)}function Ar(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
337
+ `)}function wr(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
338
338
  NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID=
339
- `}async function Sn(e,t,o="global"){let n=yn(t);if(!n||n.id==="none")return;let r=j.join(e,"apps","web");if(!Je.existsSync(r))return;let s=n.id;try{switch(s){case"posthog":mr(r),Ee(e,gr());return;case"plausible":fr(r),Ee(e,yr());return;case"umami":Sr(r),Ee(e,hr());return;case"mixpanel":Er(r),Ee(e,vr());return;case"baidu":_r(r),Ee(e,br());return;case"sensors":Pr(r),Ee(e,Cr());return;case"growingio":Ir(r),Ee(e,Ar());return;default:return}}catch(i){throw console.error(`Failed to apply analytics selection "${t}":`,i),new Error(`Analytics scaffold for "${t}" failed \u2014 see stderr for details.`)}}var wr="https://analytics.nebutra.com";function Rr(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function hn(e,t={}){Rr(t)||(async()=>{try{let o=await import("@nebutra/analytics");if(typeof o.createAnalyticsClient!="function")return;let n=o.createAnalyticsClient({posthog:{apiKey:process.env.NEBUTRA_POSTHOG_KEY??"",host:process.env.NEBUTRA_POSTHOG_HOST??wr},onError:()=>{}});if(typeof n?.track!="function")return;let r=n.track("scaffold.completed",e);r&&typeof r.then=="function"&&await r.catch(()=>{})}catch{}})()}import F from"fs";import ve from"path";function Vt(e){F.existsSync(e)&&F.rmSync(e,{recursive:!0,force:!0})}function En(e,t){let o=ve.join(e,".env.example");F.existsSync(o)?F.appendFileSync(o,`
340
- `+t):F.writeFileSync(o,t)}function vn(e,t){if(!F.existsSync(e))return;let o=F.readFileSync(e,"utf8"),n=o.replace(/export type AuthProviderId\s*=\s*"[^"]+"\s*\|\s*"[^"]+";/,`export type AuthProviderId = "${t}";`);n!==o&&F.writeFileSync(e,n)}function kr(e,t){let o=ve.join(e,"README.md");if(!F.existsSync(o)){F.writeFileSync(o,t);return}F.appendFileSync(o,`
341
- `+t)}async function _n(e,t){let o=ve.join(e,"packages","auth");if(!F.existsSync(o))return;if(t==="none"){Vt(o),kr(e,`
339
+ `}async function En(e,t,o="global"){let n=hn(t);if(!n||n.id==="none")return;let r=F.join(e,"apps","web");if(!Qe.existsSync(r))return;let i=n.id;try{switch(i){case"posthog":gr(r),ve(e,fr());return;case"plausible":yr(r),ve(e,Sr());return;case"umami":hr(r),ve(e,Er());return;case"mixpanel":vr(r),ve(e,_r());return;case"baidu":br(r),ve(e,Pr());return;case"sensors":Cr(r),ve(e,Ir());return;case"growingio":Ar(r),ve(e,wr());return;default:return}}catch(s){throw console.error(`Failed to apply analytics selection "${t}":`,s),new Error(`Analytics scaffold for "${t}" failed \u2014 see stderr for details.`)}}var Rr="https://analytics.nebutra.com";function kr(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function vn(e,t={}){kr(t)||(async()=>{try{let o=await import("@nebutra/analytics");if(typeof o.createAnalyticsClient!="function")return;let n=o.createAnalyticsClient({posthog:{apiKey:process.env.NEBUTRA_POSTHOG_KEY??"",host:process.env.NEBUTRA_POSTHOG_HOST??Rr},onError:()=>{}});if(typeof n?.track!="function")return;let r=n.track("scaffold.completed",e);r&&typeof r.then=="function"&&await r.catch(()=>{})}catch{}})()}import j from"fs";import $ from"path";function _e(e){j.existsSync(e)&&j.rmSync(e,{recursive:!0,force:!0})}function Bt(e,t){let o=$.join(e,".env.example");j.existsSync(o)?j.appendFileSync(o,`
340
+ `+t):j.writeFileSync(o,t)}function $t(e,t){if(!j.existsSync(e))return;let o=j.readFileSync(e,"utf8"),n=o.replace(/export type AuthProviderId\s*=\s*(?:"[^"]+"\s*\|\s*)+"[^"]+";/,`export type AuthProviderId = "${t}";`);n!==o&&j.writeFileSync(e,n)}function xr(e,t){let o=$.join(e,"README.md");if(!j.existsSync(o)){j.writeFileSync(o,t);return}j.appendFileSync(o,`
341
+ `+t)}async function _n(e,t){let o=$.join(e,"packages","auth");if(!j.existsSync(o))return;if(t==="none"){_e(o),xr(e,`
342
342
  ## Auth
343
343
 
344
344
  Auth was skipped at scaffold time (\`--auth=none\`). Add your preferred auth provider manually (e.g. Clerk, Better Auth).
345
- `);return}let n=ve.join(o,"src","providers"),r=ve.join(o,"src","types.ts");if(t==="clerk"){Vt(ve.join(n,"better-auth.ts")),vn(r,"clerk"),En(e,`# Clerk auth
345
+ `);return}let n=$.join(o,"src","providers"),r=$.join(o,"src","types.ts");if(t==="clerk"){_e($.join(n,"better-auth.ts")),_e($.join(n,"nextauth.ts")),$t(r,"clerk"),Bt(e,`# Clerk auth
346
346
  CLERK_PUBLISHABLE_KEY=
347
347
  CLERK_SECRET_KEY=
348
- `);return}if(t==="betterauth"){Vt(ve.join(n,"clerk.ts")),vn(r,"better-auth"),En(e,`# Better Auth
348
+ `);return}if(t==="betterauth"){_e($.join(n,"clerk.ts")),_e($.join(n,"nextauth.ts")),$t(r,"better-auth"),Bt(e,`# Better Auth
349
349
  BETTER_AUTH_SECRET=
350
350
  BETTER_AUTH_URL=http://localhost:3000
351
- `);return}}var st=[{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"}],xr=new Set(st.map(e=>e.id));function bn(e){return st.find(t=>t.id===e)}function Pn(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)xr.has(r)&&!n.has(r)&&(o.push(r),n.add(r));return o}import be from"fs";import _e from"path";function Nr(e,t){let o=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
351
+ `);return}if(t==="nextauth"){_e($.join(n,"clerk.ts")),_e($.join(n,"better-auth.ts")),$t(r,"nextauth"),Bt(e,`# NextAuth (Auth.js v5)
352
+ AUTH_SECRET=
353
+ NEXTAUTH_URL=http://localhost:3000
354
+ # OAuth (optional \u2014 leave blank to disable that provider)
355
+ GOOGLE_CLIENT_ID=
356
+ GOOGLE_CLIENT_SECRET=
357
+ GITHUB_CLIENT_ID=
358
+ GITHUB_CLIENT_SECRET=
359
+ `);return}}var at=[{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"}],Nr=new Set(at.map(e=>e.id));function bn(e){return at.find(t=>t.id===e)}function Pn(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)Nr.has(r)&&!n.has(r)&&(o.push(r),n.add(r));return o}import Pe from"fs";import be from"path";function Tr(e,t){let o=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
352
360
  // Generated by create-sailor \u2014 OAuth callback for ${e.name}
353
361
  // Primary auth provider: ${t}
354
362
  // Docs: ${e.docs}`,n={wechat:` const tokenRes = await fetch(
@@ -473,7 +481,7 @@ ${n[e.id]}
473
481
  void state;
474
482
  return NextResponse.redirect(new URL("/dashboard", req.url));
475
483
  }
476
- `}function Tr(e){return`"use client";
484
+ `}function Or(e){return`"use client";
477
485
 
478
486
  /**
479
487
  * SocialLoginButtons \u2014 generated by create-sailor.
@@ -516,23 +524,23 @@ export function SocialLoginButtons() {
516
524
  </div>
517
525
  );
518
526
  }
519
- `}function Cn(e){be.mkdirSync(e,{recursive:!0})}function Or(e,t){let o=_e.join(e,".env.example");be.existsSync(o)?be.appendFileSync(o,`
520
- `+t):be.writeFileSync(o,t)}function Ur(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,o=e.envVars.map(n=>`${n}=`).join(`
527
+ `}function Cn(e){Pe.mkdirSync(e,{recursive:!0})}function Ur(e,t){let o=be.join(e,".env.example");Pe.existsSync(o)?Pe.appendFileSync(o,`
528
+ `+t):Pe.writeFileSync(o,t)}function Lr(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,o=e.envVars.map(n=>`${n}=`).join(`
521
529
  `);return`${t}
522
530
  ${o}
523
- `}async function In(e,t,o){if(!t||t.length===0)return;let n=_e.join(e,"apps","web");if(!be.existsSync(n))return;let r=new Set,s=[];for(let l of t){if(r.has(l))continue;r.add(l);let m=bn(l);m&&s.push(m)}if(s.length===0)return;for(let l of s)Or(e,Ur(l));let i=_e.join(n,"src","app","api","auth","callback");for(let l of s){let m=_e.join(i,l.id);Cn(m);let y=_e.join(m,"route.ts");be.writeFileSync(y,Nr(l,o))}let c=_e.join(n,"src","components","auth");Cn(c);let a=_e.join(c,"SocialLoginButtons.tsx");be.writeFileSync(a,Tr(s))}import ie from"fs";import Bt from"path";var bt=[{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 An(e){return bt.find(t=>t.id===e)}var ja=bt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function wn(e){return ie.existsSync(e)?ie.readFileSync(e,"utf-8"):null}function Lr(e,t){let o=Bt.join(e,".env.example"),n=wn(o);if(n===null)return;let r=`# Cache: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
524
- `);ie.appendFileSync(o,s)}function Mr(e,t,o){let n=Bt.join(e,".env.example"),r=wn(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?ie.writeFileSync(n,r.replace(s,`${t}="${o}"`)):ie.appendFileSync(n,`${t}="${o}"
525
- `)}async function Rn(e,t,o){let n=Bt.join(e,"packages","cache");if(t==="none"){ie.existsSync(n)&&ie.rmSync(n,{recursive:!0,force:!0});return}let r=An(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${bt.map(s=>s.id).join(", ")}`);ie.existsSync(n)&&(Lr(e,r),Mr(e,"CACHE_PROVIDER",t))}var Pt=[{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 kn(e){return Pt.find(t=>t.id===e)}var Ya=Pt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import ee from"fs";import Yt from"path";function W(e,t){let o=Yt.join(e,".env.example");if(!ee.existsSync(o)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(ee.readFileSync(o,"utf-8").includes(r))return;let c=["","# =============================================",r,t.docs?`# Docs: ${t.docs}`:null,"# =============================================",...t.envVars.map(a=>`${a}=""`),""].filter(a=>a!==null).join(`
526
- `);ee.appendFileSync(o,c)}function H(e,t,o){let n=Yt.join(e,".env.example");if(!ee.existsSync(n))return;let r=ee.readFileSync(n,"utf-8"),s=`${t}="${o}"`,i=new RegExp(`^${t}=.*$`,"m");if(i.test(r)){ee.writeFileSync(n,r.replace(i,s));return}let c=r.endsWith(`
531
+ `}async function In(e,t,o){if(!t||t.length===0)return;let n=be.join(e,"apps","web");if(!Pe.existsSync(n))return;let r=new Set,i=[];for(let l of t){if(r.has(l))continue;r.add(l);let m=bn(l);m&&i.push(m)}if(i.length===0)return;for(let l of i)Ur(e,Lr(l));let s=be.join(n,"src","app","api","auth","callback");for(let l of i){let m=be.join(s,l.id);Cn(m);let y=be.join(m,"route.ts");Pe.writeFileSync(y,Tr(l,o))}let c=be.join(n,"src","components","auth");Cn(c);let a=be.join(c,"SocialLoginButtons.tsx");Pe.writeFileSync(a,Or(i))}import ae from"fs";import Yt from"path";var Ct=[{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 An(e){return Ct.find(t=>t.id===e)}var Da=Ct.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function wn(e){return ae.existsSync(e)?ae.readFileSync(e,"utf-8"):null}function Mr(e,t){let o=Yt.join(e,".env.example"),n=wn(o);if(n===null)return;let r=`# Cache: ${t.name}`;if(n.includes(r))return;let i=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(s=>`${s}=""`),""].join(`
532
+ `);ae.appendFileSync(o,i)}function Fr(e,t,o){let n=Yt.join(e,".env.example"),r=wn(n);if(r===null)return;let i=new RegExp(`^${t}=.*$`,"m");i.test(r)?ae.writeFileSync(n,r.replace(i,`${t}="${o}"`)):ae.appendFileSync(n,`${t}="${o}"
533
+ `)}async function Rn(e,t,o){let n=Yt.join(e,"packages","cache");if(t==="none"){ae.existsSync(n)&&ae.rmSync(n,{recursive:!0,force:!0});return}let r=An(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${Ct.map(i=>i.id).join(", ")}`);ae.existsSync(n)&&(Mr(e,r),Fr(e,"CACHE_PROVIDER",t))}var It=[{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 kn(e){return It.find(t=>t.id===e)}var Ya=It.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import te from"fs";import qt from"path";function H(e,t){let o=qt.join(e,".env.example");if(!te.existsSync(o)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(te.readFileSync(o,"utf-8").includes(r))return;let c=["","# =============================================",r,t.docs?`# Docs: ${t.docs}`:null,"# =============================================",...t.envVars.map(a=>`${a}=""`),""].filter(a=>a!==null).join(`
534
+ `);te.appendFileSync(o,c)}function X(e,t,o){let n=qt.join(e,".env.example");if(!te.existsSync(n))return;let r=te.readFileSync(n,"utf-8"),i=`${t}="${o}"`,s=new RegExp(`^${t}=.*$`,"m");if(s.test(r)){te.writeFileSync(n,r.replace(s,i));return}let c=r.endsWith(`
527
535
  `)?"":`
528
- `;ee.appendFileSync(n,`${c}${s}
529
- `)}function Y(e,t){let o=Yt.join(e,"packages",t);ee.existsSync(o)&&ee.rmSync(o,{recursive:!0,force:!0})}async function xn(e,t,o="global"){let n=kn(t);if(!n)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${Pt.map(r=>r.id).join(", ")}`);if(n.id==="none"){Y(e,"captcha");return}n.envVars.length>0&&W(e,{category:"Captcha",name:n.name,envVars:n.envVars,docs:n.docs}),H(e,"CAPTCHA_PROVIDER",n.id)}import It from"fs";import jr from"path";var Ct=[{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 Nn(e){return Ct.find(t=>t.id===e)}var Ja=Ct.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Tn(e,t,o="global"){let n=Nn(t);if(!n)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${Ct.map(s=>s.id).join(", ")}`);let r=jr.join(e,"apps","studio");if(n.id==="none"){Y(e,"sanity"),It.existsSync(r)&&It.rmSync(r,{recursive:!0,force:!0});return}n.id!=="sanity"&&(Y(e,"sanity"),It.existsSync(r)&&It.rmSync(r,{recursive:!0,force:!0})),n.envVars.length>0&&W(e,{category:"CMS",name:n.name,envVars:n.envVars,docs:n.docs}),H(e,"CMS_PROVIDER",n.id)}import w from"fs";import A from"path";var Fr=A.join("apps","web"),$t=A.join("src","components","compliance"),it=A.join("src","app","[locale]");function X(e){return A.join(e,Fr)}function Dr(e){w.mkdirSync(e,{recursive:!0})}function $(e,t){Dr(A.dirname(e)),w.writeFileSync(e,t,"utf8")}function qt(e,t){let o=A.join(e,".env.example");if(w.existsSync(o)){if(w.readFileSync(o,"utf8").includes(t.split(`
530
- `)[0]??""))return;w.appendFileSync(o,`
536
+ `;te.appendFileSync(n,`${c}${i}
537
+ `)}function Y(e,t){let o=qt.join(e,"packages",t);te.existsSync(o)&&te.rmSync(o,{recursive:!0,force:!0})}async function xn(e,t,o="global"){let n=kn(t);if(!n)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${It.map(r=>r.id).join(", ")}`);if(n.id==="none"){Y(e,"captcha");return}n.envVars.length>0&&H(e,{category:"Captcha",name:n.name,envVars:n.envVars,docs:n.docs}),X(e,"CAPTCHA_PROVIDER",n.id)}import wt from"fs";import Dr from"path";var At=[{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 Nn(e){return At.find(t=>t.id===e)}var Qa=At.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Tn(e,t,o="global"){let n=Nn(t);if(!n)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${At.map(i=>i.id).join(", ")}`);let r=Dr.join(e,"apps","studio");if(n.id==="none"){Y(e,"sanity"),wt.existsSync(r)&&wt.rmSync(r,{recursive:!0,force:!0});return}n.id!=="sanity"&&(Y(e,"sanity"),wt.existsSync(r)&&wt.rmSync(r,{recursive:!0,force:!0})),n.envVars.length>0&&H(e,{category:"CMS",name:n.name,envVars:n.envVars,docs:n.docs}),X(e,"CMS_PROVIDER",n.id)}import R from"fs";import w from"path";var jr=w.join("apps","web"),Gt=w.join("src","components","compliance"),ct=w.join("src","app","[locale]");function z(e){return w.join(e,jr)}function Kr(e){R.mkdirSync(e,{recursive:!0})}function q(e,t){Kr(w.dirname(e)),R.writeFileSync(e,t,"utf8")}function Wt(e,t){let o=w.join(e,".env.example");if(R.existsSync(o)){if(R.readFileSync(o,"utf8").includes(t.split(`
538
+ `)[0]??""))return;R.appendFileSync(o,`
531
539
  `+t+`
532
- `)}else w.writeFileSync(o,t+`
533
- `)}var at=`> **TEMPLATE \u2014 NOT LEGAL ADVICE.** This document is a boilerplate scaffold only.
540
+ `)}else R.writeFileSync(o,t+`
541
+ `)}var pt=`> **TEMPLATE \u2014 NOT LEGAL ADVICE.** This document is a boilerplate scaffold only.
534
542
  > Consult a qualified lawyer in every jurisdiction you operate in before publishing.
535
- > \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`,Kr=`import Link from "next/link";
543
+ > \u672C\u6587\u6863\u4E3A\u6A21\u677F\u811A\u624B\u67B6\uFF0C\u4E0D\u6784\u6210\u6CD5\u5F8B\u610F\u89C1\u3002\u53D1\u5E03\u524D\u8BF7\u54A8\u8BE2\u76F8\u5173\u53F8\u6CD5\u8F96\u533A\u7684\u5408\u683C\u5F8B\u5E08\u3002`,Vr=`import Link from "next/link";
536
544
  import { IcpFooter } from "@/components/compliance/IcpFooter";
537
545
  import { PublicSecurityFooter } from "@/components/compliance/PublicSecurityFooter";
538
546
 
@@ -583,7 +591,7 @@ export function Footer({ region = "global" }: FooterProps) {
583
591
  </footer>
584
592
  );
585
593
  }
586
- `,Vr=`export function IcpFooter() {
594
+ `,Br=`export function IcpFooter() {
587
595
  const icp = process.env.NEXT_PUBLIC_ICP_BEIAN;
588
596
  if (!icp) return null;
589
597
  return (
@@ -597,7 +605,7 @@ export function Footer({ region = "global" }: FooterProps) {
597
605
  </a>
598
606
  );
599
607
  }
600
- `,Br=`export function PublicSecurityFooter() {
608
+ `,$r=`export function PublicSecurityFooter() {
601
609
  const psb = process.env.NEXT_PUBLIC_PSB_BEIAN;
602
610
  const psbCode = process.env.NEXT_PUBLIC_PSB_CODE;
603
611
  if (!psb) return null;
@@ -841,7 +849,7 @@ function CategoryRow({ id, title, description, checked, disabled, onChange }: Ca
841
849
  </label>
842
850
  );
843
851
  }
844
- `,$r=`interface AigcDisclaimerProps {
852
+ `,qr=`interface AigcDisclaimerProps {
845
853
  className?: string;
846
854
  }
847
855
 
@@ -861,13 +869,13 @@ export function AigcDisclaimer({ className }: AigcDisclaimerProps) {
861
869
  </div>
862
870
  );
863
871
  }
864
- `,qr=`---
872
+ `,Gr=`---
865
873
  title: Privacy Policy / \u9690\u79C1\u653F\u7B56
866
874
  description: How {{COMPANY_NAME}} collects, uses, shares, and protects personal information.
867
875
  lastUpdated: 2026-01-01
868
876
  ---
869
877
 
870
- ${at}
878
+ ${pt}
871
879
 
872
880
  # Privacy Policy / \u9690\u79C1\u653F\u7B56
873
881
 
@@ -1006,13 +1014,13 @@ or in-app notification before the change takes effect.
1006
1014
  **Data Controller / \u6570\u636E\u63A7\u5236\u8005:** {{COMPANY_NAME}}
1007
1015
  **Address / \u5730\u5740:** {{COMPANY_ADDRESS}}
1008
1016
  **Email / \u90AE\u7BB1:** {{COMPANY_CONTACT_EMAIL}}
1009
- `,Gr=`---
1017
+ `,Wr=`---
1010
1018
  title: Terms of Service / \u670D\u52A1\u6761\u6B3E
1011
1019
  description: Terms governing your use of {{COMPANY_NAME}}.
1012
1020
  lastUpdated: 2026-01-01
1013
1021
  ---
1014
1022
 
1015
- ${at}
1023
+ ${pt}
1016
1024
 
1017
1025
  # Terms of Service / \u670D\u52A1\u6761\u6B3E
1018
1026
 
@@ -1125,13 +1133,13 @@ conflict-of-laws principles. Disputes shall be resolved in the competent courts
1125
1133
  ## 11. Contact / \u8054\u7CFB\u65B9\u5F0F
1126
1134
 
1127
1135
  {{COMPANY_NAME}} \xB7 {{COMPANY_ADDRESS}} \xB7 {{COMPANY_CONTACT_EMAIL}}
1128
- `,Wr=`---
1136
+ `,Hr=`---
1129
1137
  title: AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
1130
1138
  description: Disclosure required by \u7F51\u4FE1\u529E\u300A\u751F\u6210\u5F0F\u4EBA\u5DE5\u667A\u80FD\u670D\u52A1\u7BA1\u7406\u6682\u884C\u529E\u6CD5\u300B
1131
1139
  lastUpdated: 2026-01-01
1132
1140
  ---
1133
1141
 
1134
- ${at}
1142
+ ${pt}
1135
1143
 
1136
1144
  # AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
1137
1145
 
@@ -1207,13 +1215,13 @@ human professional.
1207
1215
 
1208
1216
  AI \u8F93\u51FA\u53EF\u80FD\u4E0D\u51C6\u786E\u3001\u5B58\u5728\u504F\u89C1\u6216\u8FC7\u65F6\u3002**\u8BF7\u52FF**\u5728\u672A\u7ECF\u5408\u683C\u4E13\u4E1A\u4EBA\u58EB\u72EC\u7ACB\u6838\u5B9E\u7684\u60C5\u51B5\u4E0B\uFF0C\u5C06 AI \u8F93\u51FA
1209
1217
  \u7528\u4E8E\u533B\u7597\u3001\u6CD5\u5F8B\u3001\u91D1\u878D\u6216\u5B89\u5168\u6538\u5173\u7684\u51B3\u7B56\u3002
1210
- `,Hr=`---
1218
+ `,Xr=`---
1211
1219
  title: Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
1212
1220
  description: Notice of cross-border transfer of personal information, per PIPL.
1213
1221
  lastUpdated: 2026-01-01
1214
1222
  ---
1215
1223
 
1216
- ${at}
1224
+ ${pt}
1217
1225
 
1218
1226
  # Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
1219
1227
 
@@ -1272,13 +1280,13 @@ Refusal may limit your ability to use features that rely on overseas services.
1272
1280
  - \u4F20\u8F93\u4E2D\u52A0\u5BC6 (TLS 1.2+) \u53CA\u9759\u6001\u52A0\u5BC6 (AES-256)\u3002
1273
1281
  - \u5408\u540C\u6761\u6B3E\u8981\u6C42\u5883\u5916\u63A5\u6536\u65B9\u63D0\u4F9B\u7B49\u540C\u4E8E PIPL \u7684\u4FDD\u62A4\u3002
1274
1282
  - \u8BBF\u95EE\u63A7\u5236\u3001\u5BA1\u8BA1\u65E5\u5FD7\u548C\u8FDD\u89C4\u901A\u77E5\u7A0B\u5E8F\u3002
1275
- `,Xr=`---
1283
+ `,zr=`---
1276
1284
  title: Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
1277
1285
  description: Itemized list of personal information collected, per PIPL Article 17.
1278
1286
  lastUpdated: 2026-01-01
1279
1287
  ---
1280
1288
 
1281
- ${at}
1289
+ ${pt}
1282
1290
 
1283
1291
  # Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
1284
1292
 
@@ -1314,19 +1322,19 @@ To exercise your rights (access, rectify, delete, export, withdraw consent), con
1314
1322
  **{{COMPANY_CONTACT_EMAIL}}**.
1315
1323
 
1316
1324
  \u5982\u9700\u884C\u4F7F\u60A8\u7684\u6743\u5229\uFF08\u8BBF\u95EE\u3001\u66F4\u6B63\u3001\u5220\u9664\u3001\u5BFC\u51FA\u3001\u64A4\u56DE\u540C\u610F\uFF09\uFF0C\u8BF7\u8054\u7CFB **{{COMPANY_CONTACT_EMAIL}}**\u3002
1317
- `;async function zr(e,t){let o=X(e);if(!w.existsSync(o))return;let n=A.join(o,"src","components","compliance","Footer.tsx");$(n,Kr);let r=A.join(o,"src","components","compliance","README.md");$(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(`
1318
- `))}async function Jr(e,t){let o=X(e);if(!w.existsSync(o))return;let n=A.join(o,"src","components","compliance","CookieBanner.tsx");$(n,Yr)}async function Qr(e,t){let o=X(e);if(!w.existsSync(o))return;let n=A.join(o,it,"privacy","page.mdx");$(n,qr)}async function Zr(e,t){let o=X(e);if(!w.existsSync(o))return;let n=A.join(o,it,"terms","page.mdx");$(n,Gr)}async function es(e){let t=X(e);if(!w.existsSync(t))return;let o=A.join(t,$t,"IcpFooter.tsx");$(o,Vr),qt(e,["# Chinese ICP filing (\u5DE5\u4FE1\u90E8 ICP \u5907\u6848) \u2014 required to legally host a","# public-facing site from mainland China. Apply at https://beian.miit.gov.cn/",'NEXT_PUBLIC_ICP_BEIAN="" # \u5982 \u82CFICP\u59072024XXXXXX\u53F7'].join(`
1319
- `))}async function ts(e){let t=X(e);if(!w.existsSync(t))return;let o=A.join(t,$t,"PublicSecurityFooter.tsx");$(o,Br),qt(e,["# Chinese Public Security Bureau filing (\u516C\u5B89\u8054\u7F51\u5907\u6848)","# Required in addition to ICP. Apply at http://www.beian.gov.cn/",'NEXT_PUBLIC_PSB_BEIAN="" # \u5982 \u82CF\u516C\u7F51\u5B89\u5907 32011402XXXXXX\u53F7','NEXT_PUBLIC_PSB_CODE="" # 14-digit record code'].join(`
1320
- `))}async function ns(e){let t=X(e);if(!w.existsSync(t))return;let o=A.join(t,$t,"AigcDisclaimer.tsx");$(o,$r),qt(e,["# Generative AI algorithm filing (\u7B97\u6CD5\u5907\u6848\u53F7) \u2014 required by","# \u7F51\u4FE1\u529E\u300A\u751F\u6210\u5F0F\u4EBA\u5DE5\u667A\u80FD\u670D\u52A1\u7BA1\u7406\u6682\u884C\u529E\u6CD5\u300Bfor services offered in China.",'NEXT_PUBLIC_AIGC_FILING_NUMBER="" # e.g. \u7F51\u4FE1\u7B97\u5907XXXXXXXX\u53F7'].join(`
1321
- `))}async function os(e){let t=X(e);if(!w.existsSync(t))return;let o=A.join(t,it,"aigc-disclosure","page.mdx");$(o,Wr)}async function rs(e){let t=X(e);if(!w.existsSync(t))return;let o=A.join(t,it,"cross-border-data","page.mdx");$(o,Hr)}async function ss(e){let t=X(e);if(!w.existsSync(t))return;let o=A.join(t,it,"pii-collection","page.mdx");$(o,Xr)}async function On(e,t){try{await zr(e,t),await Jr(e,t),await Qr(e,t),await Zr(e,t),(t==="cn"||t==="hybrid")&&(await es(e),await ts(e),await ns(e),await os(e),await rs(e),await ss(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 is from"fs";import as from"path";async function Un(e,t){let o=as.join(e,"nebutra.config.json");is.writeFileSync(o,JSON.stringify(t,null,2)+`
1322
- `)}import ae from"fs";import Gt from"path";function cs(e){ae.existsSync(e)&&ae.rmSync(e,{recursive:!0,force:!0})}function Ln(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function ps(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function Mn(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 ls(e,t){let o=Gt.join(e,".env.example");ae.existsSync(o)?ae.appendFileSync(o,`
1323
- `+t):ae.writeFileSync(o,t)}async function jn(e,t,o){let n=Gt.join(e,"packages","db");if(t==="none"){cs(n);return}let r=Gt.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",ls(e,`# Database (${t})
1324
- DATABASE_URL="${s}"
1325
- `),!ae.existsSync(r))return;let i=ae.readFileSync(r,"utf8"),c=i;t==="mysql"?(c=Ln(c,"mysql"),c=Mn(c)):t==="sqlite"&&(c=Ln(c,"sqlite"),c=ps(c),c=Mn(c)),c!==i&&ae.writeFileSync(r,c)}import ct from"fs";import D from"path";import{fileURLToPath as ds}from"url";var us=ds(import.meta.url),ms=D.dirname(us);async function Fn(e,t){if(t==="none")return;let o=D.join(ms,"../../templates/deploy");t==="vercel"?await ct.promises.copyFile(D.join(o,"vercel.json"),D.join(e,"vercel.json")):t==="railway"?await ct.promises.copyFile(D.join(o,"railway.toml"),D.join(e,"railway.toml")):t==="cloudflare"?await ct.promises.copyFile(D.join(o,"wrangler.toml"),D.join(e,"wrangler.toml")):t==="selfhost"&&(await ct.promises.copyFile(D.join(o,"docker-compose.yml"),D.join(e,"docker-compose.yml")),await ct.promises.copyFile(D.join(o,"Dockerfile.web"),D.join(e,"Dockerfile.web")))}import ce from"fs";import Pe from"path";import{fileURLToPath as gs}from"url";var fs=gs(import.meta.url),Dn=Pe.dirname(fs),ys=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,Kn=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function Ss(e){let t=[Pe.join(Dn,"..","templates","docs",e),Pe.join(Dn,"..","..","templates","docs",e)];for(let o of t)if(ce.existsSync(o))return o;return t[0]}async function Vn(e,t){if(t.framework==="none")return;if(!Kn.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${Kn.join(", ")}, none.`);let o=Ss(t.framework),n=Pe.join(e,"apps","docs");if(!ce.existsSync(o))throw new Error(`Docs template not found: ${o}`);Bn(o,n),Yn(n,{"{PRODUCT_NAME}":t.projectName})}function Bn(e,t){ce.mkdirSync(t,{recursive:!0});for(let o of ce.readdirSync(e,{withFileTypes:!0})){let n=Pe.join(e,o.name),r=Pe.join(t,o.name);o.isDirectory()?Bn(n,r):ce.copyFileSync(n,r)}}function Yn(e,t){for(let o of ce.readdirSync(e,{withFileTypes:!0})){let n=Pe.join(e,o.name);if(o.isDirectory())Yn(n,t);else if(ys.test(o.name)){let r=ce.readFileSync(n,"utf-8");for(let[s,i]of Object.entries(t))r=r.split(s).join(i);ce.writeFileSync(n,r)}}}import Ie from"fs";import Ce from"path";var At=[{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 $n(e){return At.find(t=>t.id===e)}var _c=At.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Ae="@nebutra/email";function Wt(e,t){Ie.mkdirSync(Ce.dirname(e),{recursive:!0}),Ie.writeFileSync(e,t)}function hs(e,t){let o=Ce.join(e,".env.example");Ie.existsSync(o)?Ie.appendFileSync(o,`
1326
- `+t):Ie.writeFileSync(o,t)}function Es(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
1325
+ `;async function Jr(e,t){let o=z(e);if(!R.existsSync(o))return;let n=w.join(o,"src","components","compliance","Footer.tsx");q(n,Vr);let r=w.join(o,"src","components","compliance","README.md");q(r,["# Compliance Components","",`Auto-generated by \`create-sailor\` for region: \`${t}\`.`,"","## Mounting the Footer","","```tsx",'import { Footer } from "@/components/compliance/Footer";','import { CookieBanner } from "@/components/compliance/CookieBanner";',"","export default function RootLayout({ children }) {"," return ("," <html>"," <body>"," {children}",` <Footer region="${t}" />`," <CookieBanner />"," </body>"," </html>"," );","}","```","","## Placeholders","","Policy MDX files contain `{{COMPANY_NAME}}`, `{{COMPANY_ADDRESS}}`,","`{{COMPANY_CONTACT_EMAIL}}`, `{{GOVERNING_JURISDICTION}}`, and","`{{AIGC_ALGORITHM_FILING_NUMBER}}`. These are filled by the `brand-apply` step.",""].join(`
1326
+ `))}async function Qr(e,t){let o=z(e);if(!R.existsSync(o))return;let n=w.join(o,"src","components","compliance","CookieBanner.tsx");q(n,Yr)}async function Zr(e,t){let o=z(e);if(!R.existsSync(o))return;let n=w.join(o,ct,"privacy","page.mdx");q(n,Gr)}async function ei(e,t){let o=z(e);if(!R.existsSync(o))return;let n=w.join(o,ct,"terms","page.mdx");q(n,Wr)}async function ti(e){let t=z(e);if(!R.existsSync(t))return;let o=w.join(t,Gt,"IcpFooter.tsx");q(o,Br),Wt(e,["# Chinese ICP filing (\u5DE5\u4FE1\u90E8 ICP \u5907\u6848) \u2014 required to legally host a","# public-facing site from mainland China. Apply at https://beian.miit.gov.cn/",'NEXT_PUBLIC_ICP_BEIAN="" # \u5982 \u82CFICP\u59072024XXXXXX\u53F7'].join(`
1327
+ `))}async function ni(e){let t=z(e);if(!R.existsSync(t))return;let o=w.join(t,Gt,"PublicSecurityFooter.tsx");q(o,$r),Wt(e,["# Chinese Public Security Bureau filing (\u516C\u5B89\u8054\u7F51\u5907\u6848)","# Required in addition to ICP. Apply at http://www.beian.gov.cn/",'NEXT_PUBLIC_PSB_BEIAN="" # \u5982 \u82CF\u516C\u7F51\u5B89\u5907 32011402XXXXXX\u53F7','NEXT_PUBLIC_PSB_CODE="" # 14-digit record code'].join(`
1328
+ `))}async function oi(e){let t=z(e);if(!R.existsSync(t))return;let o=w.join(t,Gt,"AigcDisclaimer.tsx");q(o,qr),Wt(e,["# Generative AI algorithm filing (\u7B97\u6CD5\u5907\u6848\u53F7) \u2014 required by","# \u7F51\u4FE1\u529E\u300A\u751F\u6210\u5F0F\u4EBA\u5DE5\u667A\u80FD\u670D\u52A1\u7BA1\u7406\u6682\u884C\u529E\u6CD5\u300Bfor services offered in China.",'NEXT_PUBLIC_AIGC_FILING_NUMBER="" # e.g. \u7F51\u4FE1\u7B97\u5907XXXXXXXX\u53F7'].join(`
1329
+ `))}async function ri(e){let t=z(e);if(!R.existsSync(t))return;let o=w.join(t,ct,"aigc-disclosure","page.mdx");q(o,Hr)}async function ii(e){let t=z(e);if(!R.existsSync(t))return;let o=w.join(t,ct,"cross-border-data","page.mdx");q(o,Xr)}async function si(e){let t=z(e);if(!R.existsSync(t))return;let o=w.join(t,ct,"pii-collection","page.mdx");q(o,zr)}async function On(e,t){try{await Jr(e,t),await Qr(e,t),await Zr(e,t),await ei(e,t),(t==="cn"||t==="hybrid")&&(await ti(e),await ni(e),await oi(e),await ri(e),await ii(e),await si(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 ai from"fs";import ci from"path";async function Un(e,t){let o=ci.join(e,"nebutra.config.json");ai.writeFileSync(o,JSON.stringify(t,null,2)+`
1330
+ `)}import ce from"fs";import Ht from"path";function pi(e){ce.existsSync(e)&&ce.rmSync(e,{recursive:!0,force:!0})}function Ln(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function li(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function Mn(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 di(e,t){let o=Ht.join(e,".env.example");ce.existsSync(o)?ce.appendFileSync(o,`
1331
+ `+t):ce.writeFileSync(o,t)}async function Fn(e,t,o){let n=Ht.join(e,"packages","db");if(t==="none"){pi(n);return}let r=Ht.join(n,"prisma","schema.prisma"),i;if(t==="postgresql"?i=`postgresql://postgres:postgres@localhost:5432/${o}`:t==="mysql"?i=`mysql://root:root@localhost:3306/${o}`:i="file:./dev.db",di(e,`# Database (${t})
1332
+ DATABASE_URL="${i}"
1333
+ `),!ce.existsSync(r))return;let s=ce.readFileSync(r,"utf8"),c=s;t==="mysql"?(c=Ln(c,"mysql"),c=Mn(c)):t==="sqlite"&&(c=Ln(c,"sqlite"),c=li(c),c=Mn(c)),c!==s&&ce.writeFileSync(r,c)}import Ze from"fs";import D from"path";import{fileURLToPath as ui}from"url";var mi=ui(import.meta.url),Dn=D.dirname(mi);function gi(){let e=[D.join(Dn,"..","templates","deploy"),D.join(Dn,"..","..","templates","deploy")];for(let t of e)if(Ze.existsSync(t))return t;return e[0]}async function jn(e,t){if(t==="none")return;let o=gi();t==="vercel"?await Ze.promises.copyFile(D.join(o,"vercel.json"),D.join(e,"vercel.json")):t==="railway"?await Ze.promises.copyFile(D.join(o,"railway.toml"),D.join(e,"railway.toml")):t==="cloudflare"?await Ze.promises.copyFile(D.join(o,"wrangler.toml"),D.join(e,"wrangler.toml")):t==="selfhost"&&(await Ze.promises.copyFile(D.join(o,"docker-compose.yml"),D.join(e,"docker-compose.yml")),await Ze.promises.copyFile(D.join(o,"Dockerfile.web"),D.join(e,"Dockerfile.web")))}import pe from"fs";import Ce from"path";import{fileURLToPath as fi}from"url";var yi=fi(import.meta.url),Kn=Ce.dirname(yi),Si=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,Vn=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function hi(e){let t=[Ce.join(Kn,"..","templates","docs",e),Ce.join(Kn,"..","..","templates","docs",e)];for(let o of t)if(pe.existsSync(o))return o;return t[0]}async function Bn(e,t){if(t.framework==="none")return;if(!Vn.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${Vn.join(", ")}, none.`);let o=hi(t.framework),n=Ce.join(e,"apps","docs");if(!pe.existsSync(o))throw new Error(`Docs template not found: ${o}`);$n(o,n),Yn(n,{"{PRODUCT_NAME}":t.projectName})}function $n(e,t){pe.mkdirSync(t,{recursive:!0});for(let o of pe.readdirSync(e,{withFileTypes:!0})){let n=Ce.join(e,o.name),r=Ce.join(t,o.name);o.isDirectory()?$n(n,r):pe.copyFileSync(n,r)}}function Yn(e,t){for(let o of pe.readdirSync(e,{withFileTypes:!0})){let n=Ce.join(e,o.name);if(o.isDirectory())Yn(n,t);else if(Si.test(o.name)){let r=pe.readFileSync(n,"utf-8");for(let[i,s]of Object.entries(t))r=r.split(i).join(s);pe.writeFileSync(n,r)}}}import Ae from"fs";import Ie from"path";var Rt=[{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 qn(e){return Rt.find(t=>t.id===e)}var bc=Rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var we="@nebutra/email";function Xt(e,t){Ae.mkdirSync(Ie.dirname(e),{recursive:!0}),Ae.writeFileSync(e,t)}function Ei(e,t){let o=Ie.join(e,".env.example");Ae.existsSync(o)?Ae.appendFileSync(o,`
1334
+ `+t):Ae.writeFileSync(o,t)}function vi(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
1327
1335
  `);return`${t}
1328
1336
  ${o}
1329
- `}var vs=`/**
1337
+ `}var _i=`/**
1330
1338
  * Public inputs accepted by the \`sendEmail\` wrapper.
1331
1339
  * Keep the surface minimal \u2014 individual providers may accept more, but
1332
1340
  * consumers should code against this shape for portability.
@@ -1346,14 +1354,14 @@ export interface SendEmailResult {
1346
1354
  /** Raw provider response \u2014 useful for debugging, not a stable contract. */
1347
1355
  raw?: unknown;
1348
1356
  }
1349
- `;function _s(){return`/**
1350
- * @${Ae.slice(1)} \u2014 Resend transactional email wrapper.
1357
+ `;function bi(){return`/**
1358
+ * @${we.slice(1)} \u2014 Resend transactional email wrapper.
1351
1359
  *
1352
1360
  * Docs: https://resend.com/docs
1353
1361
  */
1354
1362
  import { Resend } from "resend";
1355
1363
 
1356
- import type { SendEmailInput, SendEmailResult } from "./types.js";
1364
+ import type { SendEmailInput, SendEmailResult } from "./types";
1357
1365
 
1358
1366
  const apiKey = process.env.RESEND_API_KEY;
1359
1367
  if (!apiKey) {
@@ -1384,15 +1392,15 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1384
1392
  return { id: data?.id, raw: data };
1385
1393
  }
1386
1394
 
1387
- export type { SendEmailInput, SendEmailResult } from "./types.js";
1388
- `}function bs(){return`/**
1389
- * @${Ae.slice(1)} \u2014 Postmark transactional email wrapper.
1395
+ export type { SendEmailInput, SendEmailResult } from "./types";
1396
+ `}function Pi(){return`/**
1397
+ * @${we.slice(1)} \u2014 Postmark transactional email wrapper.
1390
1398
  *
1391
1399
  * Docs: https://postmarkapp.com/developer
1392
1400
  */
1393
1401
  import { ServerClient } from "postmark";
1394
1402
 
1395
- import type { SendEmailInput, SendEmailResult } from "./types.js";
1403
+ import type { SendEmailInput, SendEmailResult } from "./types";
1396
1404
 
1397
1405
  const apiKey = process.env.POSTMARK_API_KEY;
1398
1406
  if (!apiKey) {
@@ -1422,9 +1430,9 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1422
1430
  return { id: response.MessageID, raw: response };
1423
1431
  }
1424
1432
 
1425
- export type { SendEmailInput, SendEmailResult } from "./types.js";
1426
- `}function Ps(){return`/**
1427
- * @${Ae.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1433
+ export type { SendEmailInput, SendEmailResult } from "./types";
1434
+ `}function Ci(){return`/**
1435
+ * @${we.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1428
1436
  *
1429
1437
  * Docs: https://docs.aws.amazon.com/ses
1430
1438
  */
@@ -1433,7 +1441,7 @@ import {
1433
1441
  SESv2Client,
1434
1442
  } from "@aws-sdk/client-sesv2";
1435
1443
 
1436
- import type { SendEmailInput, SendEmailResult } from "./types.js";
1444
+ import type { SendEmailInput, SendEmailResult } from "./types";
1437
1445
 
1438
1446
  const region = process.env.AWS_SES_REGION;
1439
1447
  if (!region) {
@@ -1478,16 +1486,16 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1478
1486
  return { id: response.MessageId, raw: response };
1479
1487
  }
1480
1488
 
1481
- export type { SendEmailInput, SendEmailResult } from "./types.js";
1482
- `}function Cs(){return`/**
1483
- * @${Ae.slice(1)} \u2014 \u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001 (Aliyun DirectMail) wrapper.
1489
+ export type { SendEmailInput, SendEmailResult } from "./types";
1490
+ `}function Ii(){return`/**
1491
+ * @${we.slice(1)} \u2014 \u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001 (Aliyun DirectMail) wrapper.
1484
1492
  *
1485
1493
  * Docs: https://help.aliyun.com/product/29412.html
1486
1494
  */
1487
1495
  import Dm20151123, * as $Dm20151123 from "@alicloud/dm20151123";
1488
1496
  import * as $OpenApi from "@alicloud/openapi-client";
1489
1497
 
1490
- import type { SendEmailInput, SendEmailResult } from "./types.js";
1498
+ import type { SendEmailInput, SendEmailResult } from "./types";
1491
1499
 
1492
1500
  const accessKeyId = process.env.ALIYUN_DM_ACCESS_KEY;
1493
1501
  const accessKeySecret = process.env.ALIYUN_DM_ACCESS_SECRET;
@@ -1528,15 +1536,15 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1528
1536
  return { id: response.body?.requestId, raw: response };
1529
1537
  }
1530
1538
 
1531
- export type { SendEmailInput, SendEmailResult } from "./types.js";
1532
- `}function Is(){return`/**
1533
- * @${Ae.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1539
+ export type { SendEmailInput, SendEmailResult } from "./types";
1540
+ `}function Ai(){return`/**
1541
+ * @${we.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1534
1542
  *
1535
1543
  * Docs: https://cloud.tencent.com/document/product/1288
1536
1544
  */
1537
1545
  import tencentcloud from "tencentcloud-sdk-nodejs-ses";
1538
1546
 
1539
- import type { SendEmailInput, SendEmailResult } from "./types.js";
1547
+ import type { SendEmailInput, SendEmailResult } from "./types";
1540
1548
 
1541
1549
  const secretId = process.env.TENCENT_SECRET_ID;
1542
1550
  const secretKey = process.env.TENCENT_SECRET_KEY;
@@ -1576,15 +1584,15 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1576
1584
  return { id: response.MessageId, raw: response };
1577
1585
  }
1578
1586
 
1579
- export type { SendEmailInput, SendEmailResult } from "./types.js";
1580
- `}function As(){return`/**
1581
- * @${Ae.slice(1)} \u2014 \u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1 via SMTP (nodemailer).
1587
+ export type { SendEmailInput, SendEmailResult } from "./types";
1588
+ `}function wi(){return`/**
1589
+ * @${we.slice(1)} \u2014 \u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1 via SMTP (nodemailer).
1582
1590
  *
1583
1591
  * Docs: https://qiye.163.com/help
1584
1592
  */
1585
1593
  import nodemailer from "nodemailer";
1586
1594
 
1587
- import type { SendEmailInput, SendEmailResult } from "./types.js";
1595
+ import type { SendEmailInput, SendEmailResult } from "./types";
1588
1596
 
1589
1597
  const user = process.env.NETEASE_USER;
1590
1598
  const pass = process.env.NETEASE_PASS;
@@ -1614,25 +1622,25 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1614
1622
  return { id: response.messageId, raw: response };
1615
1623
  }
1616
1624
 
1617
- export type { SendEmailInput, SendEmailResult } from "./types.js";
1618
- `}function ws(e){switch(e){case"resend":return _s();case"postmark":return bs();case"ses":return Ps();case"aliyun-dm":return Cs();case"tencent-ses":return Is();case"netease":return As();case"none":return`export {};
1619
- `}}function Rs(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:Ae,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)+`
1620
- `}async function qn(e,t,o){if(t==="none")return;let n=$n(t);if(!n)throw new Error(`Unknown email provider "${t}". Valid ids: ${At.map(i=>i.id).join(", ")}`);let r=Ce.join(e,"packages","email"),s=Ce.join(r,"src");Ie.existsSync(s)&&Ie.rmSync(s,{recursive:!0,force:!0}),Wt(Ce.join(r,"package.json"),Rs(n)),Wt(Ce.join(s,"types.ts"),vs),Wt(Ce.join(s,"index.ts"),ws(n.id)),hs(e,Es(n))}import wt from"fs";import Gn from"path";async function Wn(e,t){let o=`# Automatically injected by create-sailor
1625
+ export type { SendEmailInput, SendEmailResult } from "./types";
1626
+ `}function Ri(e){switch(e){case"resend":return bi();case"postmark":return Pi();case"ses":return Ci();case"aliyun-dm":return Ii();case"tencent-ses":return Ai();case"netease":return wi();case"none":return`export {};
1627
+ `}}function ki(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),e.id==="aliyun-dm"&&(t["@alicloud/openapi-client"]="^0.4.12");let o={name:we,version:"0.1.0",private:!0,description:`Transactional email via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(o,null,2)+`
1628
+ `}async function Gn(e,t,o){if(t==="none")return;let n=qn(t);if(!n)throw new Error(`Unknown email provider "${t}". Valid ids: ${Rt.map(s=>s.id).join(", ")}`);let r=Ie.join(e,"packages","email"),i=Ie.join(r,"src");Ae.existsSync(i)&&Ae.rmSync(i,{recursive:!0,force:!0}),Xt(Ie.join(r,"package.json"),ki(n)),Xt(Ie.join(i,"types.ts"),_i),Xt(Ie.join(i,"index.ts"),Ri(n.id)),Ei(e,vi(n))}import kt from"fs";import Wn from"path";async function Hn(e,t){let o=`# Automatically injected by create-sailor
1621
1629
  DATABASE_URL="${String(t.databaseUrl)}"
1622
1630
 
1623
1631
  NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="${String(t.clerkPublishable)}"
1624
1632
  CLERK_SECRET_KEY="${String(t.clerkSecret)}"
1625
1633
 
1626
1634
  NEXT_PUBLIC_SITE_URL="http://localhost:3000"
1627
- `,n=Gn.join(e,".env"),r=Gn.join(e,".env.local");!wt.existsSync(n)&&!wt.existsSync(r)?wt.writeFileSync(r,o):wt.appendFileSync(r,`
1628
- `+o)}import Xn from"crypto";import pt from"fs";import Hn from"path";function we(e){return Xn.randomBytes(e).toString("base64").replace(/=+$/,"")}function ks(e){return Xn.randomBytes(e).toString("hex")}function xs(){return{AUTH_SECRET:we(32),NEXTAUTH_SECRET:we(32),BETTER_AUTH_SECRET:we(32),JWT_SECRET:we(32),WEBHOOK_SECRET:ks(16),ENCRYPTION_KEY:we(32),API_SECRET_KEY:we(32),SESSION_SECRET:we(32)}}function Ns(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Ts(e,t,o){let n=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=Ns(o);return e.replace(n,`${t}="${r}"`)}async function zn(e){let t=Hn.join(e,".env.example"),o=Hn.join(e,".env.local");if(!pt.existsSync(t))return null;try{let n=pt.readFileSync(t,"utf8"),r=xs(),i=pt.existsSync(o)?pt.readFileSync(o,"utf8"):n;for(let c of Object.keys(r))i=Ts(i,c,r[c]);return pt.writeFileSync(o,i),r}catch(n){let r=n instanceof Error?n.message:String(n);throw console.error(`[create-sailor] Failed to generate env secrets: ${r}`),new Error(`Unable to write .env.local: ${r}`)}}var Rt=[{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 Jn(e){return Rt.find(t=>t.id===e)}var Uc=Rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Qn(e,t,o="global"){let n=Jn(t);if(!n)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${Rt.map(r=>r.id).join(", ")}`);if(n.id==="none"){Y(e,"feature-flags");return}n.envVars.length>0&&W(e,{category:"Feature Flags",name:n.name,envVars:n.envVars,docs:n.docs}),H(e,"FEATURE_FLAGS_PROVIDER",n.id)}import{execFileSync as to}from"child_process";import O from"fs";import Os from"os";import pe from"path";import Us from"ignore";var Ls={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 Ms(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function js(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function no(e){return/^[0-9a-f]{7,40}$/i.test(e)}function Fs(e,t){let o=`https://github.com/${e}.git`,n=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of n)try{let s=to("git",["ls-remote",o,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!s)continue;let[i]=s.split(/\s+/);if(no(i))return i}catch{}return null}async function Ds(e,t){if(no(t))return t;let o=await fetch(`https://api.github.com/repos/${e}/commits/${encodeURIComponent(t)}`,{headers:{Accept:"application/vnd.github+json","User-Agent":"create-sailor"}});if(!o.ok){let r=Fs(e,t);if(r)return r;throw new Error(`Failed to resolve ${e}@${t} (GitHub API ${o.status})`)}let n=await o.json();if(typeof n.sha!="string"||n.sha.length===0)throw new Error(`GitHub API did not return a commit SHA for ${e}@${t}`);return n.sha}function oo(e,t,o){let n=O.readdirSync(t,{withFileTypes:!0});for(let r of n){if(r.name==="node_modules"||r.name===".git")continue;let s=pe.join(t,r.name),i=pe.relative(e,s).split(pe.sep).join("/");r.isDirectory()?(o.push(i+"/"),oo(e,s,o)):o.push(i)}}function Ks(e){let t=pe.join(e,".templateignore");if(!O.existsSync(t))return;let o=O.readFileSync(t,"utf8"),n=Us().add(o),r=[];oo(e,e,r);let s=r.map(a=>a.endsWith("/")?a.slice(0,-1):a),i=new Set(n.filter(s)),c=s.filter(a=>!i.has(a)).sort((a,l)=>l.split("/").length-a.split("/").length);for(let a of c){let l=pe.join(e,a);try{O.existsSync(l)&&O.rmSync(l,{recursive:!0,force:!0})}catch{}}try{O.existsSync(t)&&O.rmSync(t,{force:!0})}catch{}}async function Zn(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)`);O.writeFileSync(t,n);let r=O.statSync(t);if(r.size!==n.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${n.byteLength})`);return r.size}function eo(e,t){to("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function ro(e){try{let t=O.readdirSync(e);for(let o of t)O.rmSync(pe.join(e,o),{recursive:!0,force:!0})}catch{}}async function Vs(e,t){let o=O.mkdtempSync(pe.join(Os.tmpdir(),"create-sailor-")),n=pe.join(o,"template.tar.gz");try{let r=await Ds(e.repo,e.ref);await Zn(js(e.repo,r),n),eo(n,t)}catch(r){if(!e.allowMutableFallback)throw r;ro(t),await Zn(Ms(e.repo,e.ref),n),eo(n,t)}finally{O.rmSync(o,{recursive:!0,force:!0})}}async function so(e){O.mkdirSync(e,{recursive:!0});let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],n;for(let r of o){let s=Ls[r];try{if(await Vs(s,e),s.applyIgnore)try{Ks(e)}catch(i){throw new Error(`Template cloned, but .templateignore processing failed: ${i instanceof Error?i.message:String(i)}`)}return}catch(i){n=i instanceof Error?i:new Error(String(i)),ro(e)}}throw new Error(`Failed to download the template from any source. Last error: ${n?.message??"unknown"}
1635
+ `,n=Wn.join(e,".env"),r=Wn.join(e,".env.local");!kt.existsSync(n)&&!kt.existsSync(r)?kt.writeFileSync(r,o):kt.appendFileSync(r,`
1636
+ `+o)}import zn from"crypto";import lt from"fs";import Xn from"path";function Re(e){return zn.randomBytes(e).toString("base64").replace(/=+$/,"")}function xi(e){return zn.randomBytes(e).toString("hex")}function Ni(){return{AUTH_SECRET:Re(32),NEXTAUTH_SECRET:Re(32),BETTER_AUTH_SECRET:Re(32),JWT_SECRET:Re(32),WEBHOOK_SECRET:xi(16),ENCRYPTION_KEY:Re(32),API_SECRET_KEY:Re(32),SESSION_SECRET:Re(32)}}function Ti(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Oi(e,t,o){let n=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=Ti(o);return e.replace(n,`${t}="${r}"`)}async function Jn(e){let t=Xn.join(e,".env.example"),o=Xn.join(e,".env.local");if(!lt.existsSync(t))return null;try{let n=lt.readFileSync(t,"utf8"),r=Ni(),s=lt.existsSync(o)?lt.readFileSync(o,"utf8"):n;for(let c of Object.keys(r))s=Oi(s,c,r[c]);return lt.writeFileSync(o,s),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 xt=[{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 Qn(e){return xt.find(t=>t.id===e)}var Lc=xt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Zn(e,t,o="global"){let n=Qn(t);if(!n)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${xt.map(r=>r.id).join(", ")}`);if(n.id==="none"){Y(e,"feature-flags");return}n.envVars.length>0&&H(e,{category:"Feature Flags",name:n.name,envVars:n.envVars,docs:n.docs}),X(e,"FEATURE_FLAGS_PROVIDER",n.id)}import{execFileSync as no}from"child_process";import O from"fs";import Ui from"os";import le from"path";import Li from"ignore";var Mi={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 Fi(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function Di(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function oo(e){return/^[0-9a-f]{7,40}$/i.test(e)}function ji(e,t){let o=`https://github.com/${e}.git`,n=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of n)try{let i=no("git",["ls-remote",o,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!i)continue;let[s]=i.split(/\s+/);if(oo(s))return s}catch{}return null}async function Ki(e,t){if(oo(t))return t;let o=await fetch(`https://api.github.com/repos/${e}/commits/${encodeURIComponent(t)}`,{headers:{Accept:"application/vnd.github+json","User-Agent":"create-sailor"}});if(!o.ok){let r=ji(e,t);if(r)return r;throw new Error(`Failed to resolve ${e}@${t} (GitHub API ${o.status})`)}let n=await o.json();if(typeof n.sha!="string"||n.sha.length===0)throw new Error(`GitHub API did not return a commit SHA for ${e}@${t}`);return n.sha}function ro(e,t,o){let n=O.readdirSync(t,{withFileTypes:!0});for(let r of n){if(r.name==="node_modules"||r.name===".git")continue;let i=le.join(t,r.name),s=le.relative(e,i).split(le.sep).join("/");r.isDirectory()?(o.push(s+"/"),ro(e,i,o)):o.push(s)}}function Vi(e){let t=le.join(e,".templateignore");if(!O.existsSync(t))return;let o=O.readFileSync(t,"utf8"),n=Li().add(o),r=[];ro(e,e,r);let i=r.map(a=>a.endsWith("/")?a.slice(0,-1):a),s=new Set(n.filter(i)),c=i.filter(a=>!s.has(a)).sort((a,l)=>l.split("/").length-a.split("/").length);for(let a of c){let l=le.join(e,a);try{O.existsSync(l)&&O.rmSync(l,{recursive:!0,force:!0})}catch{}}try{O.existsSync(t)&&O.rmSync(t,{force:!0})}catch{}}async function eo(e,t){let o=await fetch(e,{headers:{Accept:"application/octet-stream","User-Agent":"create-sailor"}});if(!o.ok)throw new Error(`Failed to download archive (${o.status})`);let n=Buffer.from(await o.arrayBuffer());if(n.byteLength<1024)throw new Error(`Downloaded archive is unexpectedly small (${n.byteLength} bytes)`);O.writeFileSync(t,n);let r=O.statSync(t);if(r.size!==n.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${n.byteLength})`);return r.size}function to(e,t){no("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function io(e){try{let t=O.readdirSync(e);for(let o of t)O.rmSync(le.join(e,o),{recursive:!0,force:!0})}catch{}}async function Bi(e,t){let o=O.mkdtempSync(le.join(Ui.tmpdir(),"create-sailor-")),n=le.join(o,"template.tar.gz");try{let r=await Ki(e.repo,e.ref);await eo(Di(e.repo,r),n),to(n,t)}catch(r){if(!e.allowMutableFallback)throw r;io(t),await eo(Fi(e.repo,e.ref),n),to(n,t)}finally{O.rmSync(o,{recursive:!0,force:!0})}}async function so(e){O.mkdirSync(e,{recursive:!0});let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],n;for(let r of o){let i=Mi[r];try{if(await Bi(i,e),i.applyIgnore)try{Vi(e)}catch(s){throw new Error(`Template cloned, but .templateignore processing failed: ${s instanceof Error?s.message:String(s)}`)}return}catch(s){n=s instanceof Error?s:new Error(String(s)),io(e)}}throw new Error(`Failed to download the template from any source. Last error: ${n?.message??"unknown"}
1629
1637
 
1630
1638
  Ensure you have internet access and 'tar' installed.
1631
- You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import Re from"fs";import Ht from"path";async function io(e,t){let o=Ht.join(e,"packages","mcp");if(t==="off"){Re.existsSync(o)&&Re.rmSync(o,{recursive:!0,force:!0});let r=Ht.join(e,"packages","cli","src","commands","mcp-server.ts");Re.existsSync(r)&&Re.rmSync(r,{force:!0});return}let n=Ht.join(e,".env.example");if(Re.existsSync(n)){let r=Re.readFileSync(n,"utf-8"),s="# MCP Server (Agent-friendly API)";if(!r.includes(s)){let i=["","# =============================================",s,"# Docs: https://modelcontextprotocol.io","# =============================================","# MCP server exposes your SaaS capabilities to AI agents via MCP protocol.","# Run: pnpm mcp-server (starts stdio server)","# No config required for stdio transport. HTTP transport needs:",'MCP_HTTP_PORT="3100"','MCP_API_KEY=""',""].join(`
1632
- `);Re.appendFileSync(n,i)}}}import lt from"fs";import ao from"path";async function co(e,t,o){let n=ao.join(e,"packages","metering"),r;if(t==="auto"?r=o!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){lt.existsSync(n)&&lt.rmSync(n,{recursive:!0,force:!0});return}let s=ao.join(e,".env.example");if(!lt.existsSync(s))return;let i=lt.readFileSync(s,"utf-8"),c="# Metering (usage-based billing)";if(!i.includes(c)){let a=["","# =============================================",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(`
1633
- `);lt.appendFileSync(s,a)}}import te from"fs";import U from"path";var po=[{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:""}],Jc=po.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function lo(e){return po.find(t=>t.id===e)}var Xt={sentry:{"@sentry/nextjs":"^8.45.0"},datadog:{"dd-trace":"^5.32.0","@datadog/browser-rum":"^5.30.0"},bugsnag:{"@bugsnag/js":"^8.2.0","@bugsnag/plugin-react":"^8.2.0"}};function Bs(e){te.mkdirSync(e,{recursive:!0})}function zt(e,t){let o=U.join(e,"package.json");if(!te.existsSync(o))return;let n;try{n=JSON.parse(te.readFileSync(o,"utf-8"))}catch(c){console.error(`Failed to parse ${o}:`,c);return}let s={...n.dependencies??{}};for(let[c,a]of Object.entries(t))s[c]||(s[c]=a);let i={...n,dependencies:s};te.writeFileSync(o,JSON.stringify(i,null,2)+`
1634
- `)}function z(e,t){Bs(U.dirname(e)),te.writeFileSync(e,t)}function dt(e,t){let o=U.join(e,".env.example");te.existsSync(o)?te.appendFileSync(o,`
1635
- `+t):te.writeFileSync(o,t)}function Ys(e){let t=`import * as Sentry from "@sentry/nextjs";
1639
+ You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import ke from"fs";import zt from"path";async function ao(e,t){let o=zt.join(e,"packages","mcp");if(t==="off"){ke.existsSync(o)&&ke.rmSync(o,{recursive:!0,force:!0});let r=zt.join(e,"packages","cli","src","commands","mcp-server.ts");ke.existsSync(r)&&ke.rmSync(r,{force:!0});return}let n=zt.join(e,".env.example");if(ke.existsSync(n)){let r=ke.readFileSync(n,"utf-8"),i="# MCP Server (Agent-friendly API)";if(!r.includes(i)){let s=["","# =============================================",i,"# 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(`
1640
+ `);ke.appendFileSync(n,s)}}}import dt from"fs";import co from"path";async function po(e,t,o){let n=co.join(e,"packages","metering"),r;if(t==="auto"?r=o!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){dt.existsSync(n)&&dt.rmSync(n,{recursive:!0,force:!0});return}let i=co.join(e,".env.example");if(!dt.existsSync(i))return;let s=dt.readFileSync(i,"utf-8"),c="# Metering (usage-based billing)";if(!s.includes(c)){let a=["","# =============================================",c,"# Docs: see packages/commerce/metering/README.md","# =============================================","# ClickHouse-based metering pipeline for consumption billing.",'CLICKHOUSE_URL=""','CLICKHOUSE_USER="default"','CLICKHOUSE_PASSWORD=""','CLICKHOUSE_DATABASE="metering"',""].join(`
1641
+ `);dt.appendFileSync(i,a)}}import ne from"fs";import U from"path";var lo=[{id:"sentry",name:"Sentry",region:"both",envVars:["SENTRY_DSN","NEXT_PUBLIC_SENTRY_DSN"],docs:"https://docs.sentry.io",pkg:"@sentry/nextjs",instrumentationFile:"apps/web/instrumentation.ts"},{id:"datadog",name:"Datadog",region:"global",envVars:["DD_API_KEY","DD_APP_KEY","DD_SITE"],docs:"https://docs.datadoghq.com",pkg:"dd-trace",instrumentationFile:"apps/web/instrumentation.ts"},{id:"bugsnag",name:"Bugsnag",region:"global",envVars:["BUGSNAG_API_KEY","NEXT_PUBLIC_BUGSNAG_API_KEY"],docs:"https://docs.bugsnag.com",pkg:"@bugsnag/js",instrumentationFile:"apps/web/src/lib/monitoring/bugsnag.ts"},{id:"aliyun-arms",name:"\u963F\u91CC\u4E91 ARMS",region:"cn",envVars:["ALIYUN_ARMS_LICENSE_KEY","ALIYUN_ARMS_APP_NAME","NEXT_PUBLIC_ARMS_PID"],docs:"https://help.aliyun.com/product/34364.html",instrumentationFile:"apps/web/src/components/monitoring/ArmsScript.tsx"},{id:"tingyun",name:"\u542C\u4E91 TingYun",region:"cn",envVars:["TINGYUN_LICENSE_KEY","NEXT_PUBLIC_TINGYUN_APP_KEY"],docs:"https://www.tingyun.com/docs",instrumentationFile:"apps/web/src/components/monitoring/TingYunScript.tsx"},{id:"none",name:"None",region:"both",envVars:[],docs:""}],Qc=lo.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function uo(e){return lo.find(t=>t.id===e)}var Jt={sentry:{"@sentry/nextjs":"^8.45.0"},datadog:{"dd-trace":"^5.32.0","@datadog/browser-rum":"^5.30.0"},bugsnag:{"@bugsnag/js":"^8.2.0","@bugsnag/plugin-react":"^8.2.0"}};function $i(e){ne.mkdirSync(e,{recursive:!0})}function Qt(e,t){let o=U.join(e,"package.json");if(!ne.existsSync(o))return;let n;try{n=JSON.parse(ne.readFileSync(o,"utf-8"))}catch(c){console.error(`Failed to parse ${o}:`,c);return}let i={...n.dependencies??{}};for(let[c,a]of Object.entries(t))i[c]||(i[c]=a);let s={...n,dependencies:i};ne.writeFileSync(o,JSON.stringify(s,null,2)+`
1642
+ `)}function J(e,t){$i(U.dirname(e)),ne.writeFileSync(e,t)}function ut(e,t){let o=U.join(e,".env.example");ne.existsSync(o)?ne.appendFileSync(o,`
1643
+ `+t):ne.writeFileSync(o,t)}function Yi(e){let t=`import * as Sentry from "@sentry/nextjs";
1636
1644
 
1637
1645
  Sentry.init({
1638
1646
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
@@ -1675,14 +1683,14 @@ export async function register() {
1675
1683
  }
1676
1684
 
1677
1685
  export { captureRequestError as onRequestError } from "@sentry/nextjs";
1678
- `;z(U.join(e,"sentry.client.config.ts"),t),z(U.join(e,"sentry.server.config.ts"),o),z(U.join(e,"sentry.edge.config.ts"),n),z(U.join(e,"instrumentation.ts"),r)}function $s(){return`# Sentry \u2014 error tracking + performance monitoring
1686
+ `;J(U.join(e,"sentry.client.config.ts"),t),J(U.join(e,"sentry.server.config.ts"),o),J(U.join(e,"sentry.edge.config.ts"),n),J(U.join(e,"instrumentation.ts"),r)}function qi(){return`# Sentry \u2014 error tracking + performance monitoring
1679
1687
  # Get your DSN from https://sentry.io/settings/projects/<project>/keys/
1680
1688
  SENTRY_DSN=
1681
1689
  NEXT_PUBLIC_SENTRY_DSN=
1682
1690
  SENTRY_ORG=
1683
1691
  SENTRY_PROJECT=
1684
1692
  SENTRY_AUTH_TOKEN=
1685
- `}function qs(e){let t=`/**
1693
+ `}function Gi(e){let t=`/**
1686
1694
  * Next.js instrumentation hook \u2014 wires Datadog APM (dd-trace) into Node runtime.
1687
1695
  * Edge runtime is not supported by dd-trace; only nodejs is initialized.
1688
1696
  */
@@ -1730,7 +1738,7 @@ export function initDatadogRum(): void {
1730
1738
  });
1731
1739
  initialized = true;
1732
1740
  }
1733
- `;z(U.join(e,"instrumentation.ts"),t),z(U.join(e,"src","lib","monitoring","datadog-rum.ts"),o)}function Gs(){return`# Datadog \u2014 APM + RUM
1741
+ `;J(U.join(e,"instrumentation.ts"),t),J(U.join(e,"src","lib","monitoring","datadog-rum.ts"),o)}function Wi(){return`# Datadog \u2014 APM + RUM
1734
1742
  # Server APM (dd-trace)
1735
1743
  DD_API_KEY=
1736
1744
  DD_APP_KEY=
@@ -1745,7 +1753,7 @@ NEXT_PUBLIC_DD_SITE=datadoghq.com
1745
1753
  NEXT_PUBLIC_DD_SERVICE=sailor-web
1746
1754
  NEXT_PUBLIC_DD_ENV=production
1747
1755
  NEXT_PUBLIC_DD_VERSION=
1748
- `}function Ws(e){let t=`/**
1756
+ `}function Hi(e){let t=`/**
1749
1757
  * Bugsnag server-side initialization.
1750
1758
  * Import this once at the top of your server entrypoint or a shared init module.
1751
1759
  */
@@ -1794,11 +1802,11 @@ export function getBugsnagErrorBoundary() {
1794
1802
  errorBoundary = plugin.createErrorBoundary(React) as typeof errorBoundary;
1795
1803
  return errorBoundary;
1796
1804
  }
1797
- `;z(U.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),z(U.join(e,"src","lib","monitoring","bugsnag.client.tsx"),o)}function Hs(){return`# Bugsnag \u2014 error tracking
1805
+ `;J(U.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),J(U.join(e,"src","lib","monitoring","bugsnag.client.tsx"),o)}function Xi(){return`# Bugsnag \u2014 error tracking
1798
1806
  BUGSNAG_API_KEY=
1799
1807
  NEXT_PUBLIC_BUGSNAG_API_KEY=
1800
1808
  APP_VERSION=
1801
- `}function Xs(e){z(U.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1809
+ `}function zi(e){J(U.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1802
1810
  /**
1803
1811
  * \u963F\u91CC\u4E91 ARMS (Application Real-time Monitoring Service) browser agent.
1804
1812
  * Injects the official JS agent via next/script.
@@ -1819,11 +1827,11 @@ export function ArmsScript() {
1819
1827
  />
1820
1828
  );
1821
1829
  }
1822
- `)}function zs(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1830
+ `)}function Ji(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1823
1831
  ALIYUN_ARMS_LICENSE_KEY=
1824
1832
  ALIYUN_ARMS_APP_NAME=
1825
1833
  NEXT_PUBLIC_ARMS_PID=
1826
- `}function Js(e){z(U.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1834
+ `}function Qi(e){J(U.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1827
1835
  /**
1828
1836
  * \u542C\u4E91 Browser Agent (\u524D\u7AEF\u6027\u80FD\u76D1\u63A7).
1829
1837
  * Docs: https://www.tingyun.com/docs
@@ -1841,12 +1849,12 @@ export function TingYunScript() {
1841
1849
  />
1842
1850
  );
1843
1851
  }
1844
- `)}function Qs(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1852
+ `)}function Zi(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1845
1853
  TINGYUN_LICENSE_KEY=
1846
1854
  NEXT_PUBLIC_TINGYUN_APP_KEY=
1847
- `}async function uo(e,t,o="global"){let n=lo(t);if(!n||n.id==="none")return;let r=U.join(e,"apps","web");if(!te.existsSync(r))return;let s=n.id;try{switch(s){case"sentry":Ys(r),zt(r,Xt.sentry),dt(e,$s());return;case"datadog":qs(r),zt(r,Xt.datadog),dt(e,Gs());return;case"bugsnag":Ws(r),zt(r,Xt.bugsnag),dt(e,Hs());return;case"aliyun-arms":Xs(r),dt(e,zs());return;case"tingyun":Js(r),dt(e,Qs());return;default:return}}catch(i){throw console.error(`Failed to apply monitoring selection "${t}":`,i),new Error(`Monitoring scaffold for "${t}" failed \u2014 see stderr for details.`)}}var kt=[{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 mo(e){return kt.find(t=>t.id===e)}var op=kt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function go(e,t,o="global"){let n=mo(t);if(!n)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${kt.map(r=>r.id).join(", ")}`);if(n.id==="none"){Y(e,"notifications");return}n.envVars.length>0&&W(e,{category:"Notifications",name:n.name,envVars:n.envVars,docs:n.docs}),H(e,"NOTIFICATIONS_PROVIDER",n.id)}import Jt from"fs";import Zs from"path";async function fo(e,t){let o=Zs.join(e,"package.json");if(Jt.existsSync(o)){let n=Jt.readFileSync(o,"utf8"),r=JSON.parse(n);r.name=t,r.version="0.1.0",Jt.writeFileSync(o,JSON.stringify(r,null,2)+`
1848
- `)}}import ne from"fs";import ut from"path";var ei=["stripe","lemonsqueezy","chinapay","polar"];function yo(e){ne.existsSync(e)&&ne.rmSync(e,{recursive:!0,force:!0})}function ti(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function ni(e,t){let o=ut.join(e,".env.example");ne.existsSync(o)?ne.appendFileSync(o,`
1849
- `+t):ne.writeFileSync(o,t)}function oi(e){switch(e){case"stripe":return`# Stripe
1855
+ `}async function mo(e,t,o="global"){let n=uo(t);if(!n||n.id==="none")return;let r=U.join(e,"apps","web");if(!ne.existsSync(r))return;let i=n.id;try{switch(i){case"sentry":Yi(r),Qt(r,Jt.sentry),ut(e,qi());return;case"datadog":Gi(r),Qt(r,Jt.datadog),ut(e,Wi());return;case"bugsnag":Hi(r),Qt(r,Jt.bugsnag),ut(e,Xi());return;case"aliyun-arms":zi(r),ut(e,Ji());return;case"tingyun":Qi(r),ut(e,Zi());return;default:return}}catch(s){throw console.error(`Failed to apply monitoring selection "${t}":`,s),new Error(`Monitoring scaffold for "${t}" failed \u2014 see stderr for details.`)}}var Nt=[{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 go(e){return Nt.find(t=>t.id===e)}var rp=Nt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function fo(e,t,o="global"){let n=go(t);if(!n)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${Nt.map(r=>r.id).join(", ")}`);if(n.id==="none"){Y(e,"notifications");return}n.envVars.length>0&&H(e,{category:"Notifications",name:n.name,envVars:n.envVars,docs:n.docs}),X(e,"NOTIFICATIONS_PROVIDER",n.id)}import Zt from"fs";import es from"path";async function yo(e,t){let o=es.join(e,"package.json");if(Zt.existsSync(o)){let n=Zt.readFileSync(o,"utf8"),r=JSON.parse(n);r.name=t,r.version="0.1.0",Zt.writeFileSync(o,JSON.stringify(r,null,2)+`
1856
+ `)}}import oe from"fs";import mt from"path";var ts=["stripe","lemonsqueezy","chinapay","polar"];function So(e){oe.existsSync(e)&&oe.rmSync(e,{recursive:!0,force:!0})}function ns(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function os(e,t){let o=mt.join(e,".env.example");oe.existsSync(o)?oe.appendFileSync(o,`
1857
+ `+t):oe.writeFileSync(o,t)}function rs(e){switch(e){case"stripe":return`# Stripe
1850
1858
  STRIPE_SECRET_KEY=
1851
1859
  STRIPE_WEBHOOK_SECRET=
1852
1860
  `;case"lemon":return`# Lemon Squeezy
@@ -1861,13 +1869,13 @@ CHINAPAY_WECHAT_ENABLED=true
1861
1869
  CHINAPAY_APP_ID=
1862
1870
  CHINAPAY_APP_SECRET=
1863
1871
  CHINAPAY_ALIPAY_ENABLED=true
1864
- `}}async function So(e,t){let o=ut.join(e,"packages","billing");if(!ne.existsSync(o))return;if(t==="none"){yo(o);return}let n=ut.join(o,"src"),r=new Set(ti(t));for(let i of ei)r.has(i)||yo(ut.join(n,i));let s=ut.join(n,"checkout","types.ts");if(ne.existsSync(s)){let i=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",c=ne.readFileSync(s,"utf8"),a=c.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${i}";`);a!==c&&ne.writeFileSync(s,a)}ni(e,oi(t))}import le from"fs";import Qe from"path";var vo=new Set(["siliconflow","volcengine-ark","bailian","moonshot"]),Qt=/@sailor:([^\s*]+)/;function ri(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=>vo.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 ho(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function Eo(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function _o(e,t){let o=e.split(`
1865
- `),n=[],r=e.includes("#"),s=0;for(;s<o.length;){let i=o[s],c=i.match(Qt);if(!c){n.push(i),s++;continue}let{marker:a,keep:l}=ri(c[1],t);if(a==="registry-entries"){n.push(r?Eo(i):ho(i)),s++;continue}if(l){let m=r?Eo(i):ho(i);m.trim().length>0&&n.push(m);let y=s+1;for(;y<o.length&&o[y].trim()!==""&&!Qt.test(o[y]);)n.push(o[y]),y++;y<o.length&&o[y].trim()===""&&(n.push(o[y]),y++),s=y}else{let m=s+1;for(;m<o.length&&o[m].trim()!==""&&!Qt.test(o[m]);)m++;m<o.length&&o[m].trim()===""&&m++,s=m}}return si(n.join(`
1866
- `),t)}function si(e,t){let{providerIds:o,customEndpoint:n}=t,r=new Set;for(let l of o)["openai","anthropic","google","mistral","xai"].includes(l)&&r.add(l),r.add(l.replace(/-/g,"_")),r.add(l);n&&r.add("custom");let s=/createProviderRegistry\(\{([\s\S]*?)\}\)/,i=e.match(s);if(!i)return e;let a=i[1].split(`
1872
+ `}}async function ho(e,t){let o=mt.join(e,"packages","billing");if(!oe.existsSync(o))return;if(t==="none"){So(o);return}let n=mt.join(o,"src"),r=new Set(ns(t));for(let s of ts)r.has(s)||So(mt.join(n,s));let i=mt.join(n,"checkout","types.ts");if(oe.existsSync(i)){let s=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",c=oe.readFileSync(i,"utf8"),a=c.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${s}";`);a!==c&&oe.writeFileSync(i,a)}os(e,rs(t))}import de from"fs";import et from"path";var _o=new Set(["siliconflow","volcengine-ark","bailian","moonshot"]),en=/@sailor:([^\s*]+)/;function is(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(i=>_o.has(i));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 Eo(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function vo(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function bo(e,t){let o=e.split(`
1873
+ `),n=[],r=e.includes("#"),i=0;for(;i<o.length;){let s=o[i],c=s.match(en);if(!c){n.push(s),i++;continue}let{marker:a,keep:l}=is(c[1],t);if(a==="registry-entries"){n.push(r?vo(s):Eo(s)),i++;continue}if(l){let m=r?vo(s):Eo(s);m.trim().length>0&&n.push(m);let y=i+1;for(;y<o.length&&o[y].trim()!==""&&!en.test(o[y]);)n.push(o[y]),y++;y<o.length&&o[y].trim()===""&&(n.push(o[y]),y++),i=y}else{let m=i+1;for(;m<o.length&&o[m].trim()!==""&&!en.test(o[m]);)m++;m<o.length&&o[m].trim()===""&&m++,i=m}}return ss(n.join(`
1874
+ `),t)}function ss(e,t){let{providerIds:o,customEndpoint:n}=t,r=new Set;for(let l of o)["openai","anthropic","google","mistral","xai"].includes(l)&&r.add(l),r.add(l.replace(/-/g,"_")),r.add(l);n&&r.add("custom");let i=/createProviderRegistry\(\{([\s\S]*?)\}\)/,s=e.match(i);if(!s)return e;let a=s[1].split(`
1867
1875
  `).filter(l=>{let m=l.trim();if(m===""||m.startsWith("//"))return!0;let y=m.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return y?r.has(y[1]):!0}).join(`
1868
- `);return e.replace(s,`createProviderRegistry({${a}})`)}function ii(e,t){let o=Qe.join(t,"registry.ts.template"),n=le.readFileSync(o,"utf-8");return _o(n,e)}function ai(e,t){let o=Qe.join(t,".env.example.template"),n=le.readFileSync(o,"utf-8");return _o(n,e)}async function bo(e,t,o){let n=ii(t,o),r=ai(t,o),s=Qe.join(e,"packages/agents/src");await le.promises.mkdir(s,{recursive:!0}),await le.promises.writeFile(Qe.join(s,"registry.ts"),n),await le.promises.appendFile(Qe.join(e,".env.example"),`
1869
- `+r);let i={ai:"latest"},{providerIds:c,customEndpoint:a}=t;(c.includes("openai")||a||c.some(m=>vo.has(m)))&&(i["@ai-sdk/openai"]="latest",i["@ai-sdk/openai-compatible"]="latest"),c.includes("anthropic")&&(i["@ai-sdk/anthropic"]="latest"),c.includes("google")&&(i["@ai-sdk/google"]="latest"),c.includes("mistral")&&(i["@ai-sdk/mistral"]="latest"),c.includes("xai")&&(i["@ai-sdk/openai"]="latest");let l=Qe.join(e,"package.json");if(le.existsSync(l)){let m=JSON.parse(await le.promises.readFile(l,"utf-8"));m.dependencies||(m.dependencies={});for(let[y,k]of Object.entries(i))m.dependencies[y]=k;await le.promises.writeFile(l,JSON.stringify(m,null,2)+`
1870
- `)}}import f from"fs";import d from"path";function Po(e,t){if(!f.existsSync(e))return;let o=f.readdirSync(e);for(let n of o){let r=d.join(e,n);f.statSync(r).isDirectory()?Po(r,t):t(r)}}async function Co(e,t){let o=d.join(e,"package.json");if(!f.existsSync(o))return;let n=JSON.parse(f.readFileSync(o,"utf8"));if(t.orm!=="prisma"){let r=d.join(e,"packages","db");if(f.existsSync(r)){let s=d.join(r,"prisma");f.existsSync(s)&&f.rmSync(s,{recursive:!0,force:!0});let i=d.join(r,"package.json");if(f.existsSync(i)){let a=JSON.parse(f.readFileSync(i,"utf8"));a.dependencies&&delete a.dependencies["@prisma/client"],a.devDependencies&&delete a.devDependencies.prisma,f.writeFileSync(i,JSON.stringify(a,null,2)+`
1876
+ `);return e.replace(i,`createProviderRegistry({${a}})`)}function as(e,t){let o=et.join(t,"registry.ts.template"),n=de.readFileSync(o,"utf-8");return bo(n,e)}function cs(e,t){let o=et.join(t,".env.example.template"),n=de.readFileSync(o,"utf-8");return bo(n,e)}async function Po(e,t,o){let n=as(t,o),r=cs(t,o),i=et.join(e,"packages/ai/agents/src");await de.promises.mkdir(i,{recursive:!0}),await de.promises.writeFile(et.join(i,"registry.ts"),n),await de.promises.appendFile(et.join(e,".env.example"),`
1877
+ `+r);let s={ai:"latest"},{providerIds:c,customEndpoint:a}=t;(c.includes("openai")||a||c.some(m=>_o.has(m)))&&(s["@ai-sdk/openai"]="latest",s["@ai-sdk/openai-compatible"]="latest"),c.includes("anthropic")&&(s["@ai-sdk/anthropic"]="latest"),c.includes("google")&&(s["@ai-sdk/google"]="latest"),c.includes("mistral")&&(s["@ai-sdk/mistral"]="latest"),c.includes("xai")&&(s["@ai-sdk/openai"]="latest");let l=et.join(e,"package.json");if(de.existsSync(l)){let m=JSON.parse(await de.promises.readFile(l,"utf-8"));m.dependencies||(m.dependencies={});for(let[y,x]of Object.entries(s))m.dependencies[y]=x;await de.promises.writeFile(l,JSON.stringify(m,null,2)+`
1878
+ `)}}import f from"fs";import d from"path";function Co(e,t){if(!f.existsSync(e))return;let o=f.readdirSync(e);for(let n of o){let r=d.join(e,n);f.statSync(r).isDirectory()?Co(r,t):t(r)}}async function Io(e,t){let o=d.join(e,"package.json");if(!f.existsSync(o))return;let n=JSON.parse(f.readFileSync(o,"utf8"));if(t.orm!=="prisma"){let r=d.join(e,"packages","db");if(f.existsSync(r)){let i=d.join(r,"prisma");f.existsSync(i)&&f.rmSync(i,{recursive:!0,force:!0});let s=d.join(r,"package.json");if(f.existsSync(s)){let a=JSON.parse(f.readFileSync(s,"utf8"));a.dependencies&&delete a.dependencies["@prisma/client"],a.devDependencies&&delete a.devDependencies.prisma,f.writeFileSync(s,JSON.stringify(a,null,2)+`
1871
1879
  `)}let c=d.join(r,"src","index.ts");f.existsSync(c)&&f.writeFileSync(c,`
1872
1880
  export const prisma = {} as any;
1873
1881
  export const db = {} as any;
@@ -1914,7 +1922,7 @@ export type UsageAggregate = any;
1914
1922
  export type UsageLedgerEntry = any;
1915
1923
  export type UsageType = any;
1916
1924
  export type UsageLedgerSource = any;
1917
- `)}n.scripts?.postinstall&&(n.scripts.postinstall=n.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let r=d.join(e,"apps");if(f.existsSync(r)){let s=f.readdirSync(r);for(let i of s){let c=d.join(r,i);if(!f.statSync(c).isDirectory())continue;let a=d.join(c,"src","app");if(!f.existsSync(a))continue;["[lang]","[locale]"].forEach(b=>{let u=d.join(a,b);if(f.existsSync(u)){let T=f.readdirSync(u);for(let yt of T)f.renameSync(d.join(u,yt),d.join(a,yt));f.rmdirSync(u)}}),["src/middleware.ts","middleware.ts"].forEach(b=>{let u=d.join(c,b);f.existsSync(u)&&f.rmSync(u)});let l=d.join(c,"src","lib");f.existsSync(l)||f.mkdirSync(l,{recursive:!0});let m=d.join(l,"mock-i18n.ts");f.writeFileSync(m,`
1925
+ `)}n.scripts?.postinstall&&(n.scripts.postinstall=n.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let r=d.join(e,"apps");if(f.existsSync(r)){let i=f.readdirSync(r);for(let s of i){let c=d.join(r,s);if(!f.statSync(c).isDirectory())continue;let a=d.join(c,"src","app");if(!f.existsSync(a))continue;["[lang]","[locale]"].forEach(b=>{let u=d.join(a,b);if(f.existsSync(u)){let T=f.readdirSync(u);for(let ht of T)f.renameSync(d.join(u,ht),d.join(a,ht));f.rmdirSync(u)}}),["src/middleware.ts","middleware.ts"].forEach(b=>{let u=d.join(c,b);f.existsSync(u)&&f.rmSync(u)});let l=d.join(c,"src","lib");f.existsSync(l)||f.mkdirSync(l,{recursive:!0});let m=d.join(l,"mock-i18n.ts");f.writeFileSync(m,`
1918
1926
  import React from 'react';
1919
1927
  export function useTranslations(namespace?: string): any { return (key: string) => key; }
1920
1928
  export function useLocale() { return 'en'; }
@@ -1932,7 +1940,7 @@ export const useRouter = () => ({ push: (...args: any[]) => {}, replace: (...arg
1932
1940
  export default function createMiddleware(...args: any[]) { return (req: any) => req; }
1933
1941
  export function createNavigation(...args: any[]) { return { Link, redirect, usePathname, useRouter, getPathname: () => '/' }; }
1934
1942
  export function defineRouting<T>(config: T): T { return config; }
1935
- `);let k=d.join(l,"mock-i18n.d.ts");f.writeFileSync(k,`declare module '@/lib/mock-i18n' {
1943
+ `);let x=d.join(l,"mock-i18n.d.ts");f.writeFileSync(x,`declare module '@/lib/mock-i18n' {
1936
1944
  export function useTranslations(namespace?: string): any;
1937
1945
  export function useLocale(): string;
1938
1946
  export const NextIntlClientProvider: React.FC<any>;
@@ -1953,16 +1961,16 @@ export function defineRouting<T>(config: T): T { return config; }
1953
1961
  `),f.writeFileSync(d.join(l,"mock-i18n-index.ts"),`
1954
1962
  export * from './mock-i18n';
1955
1963
  export { default } from './mock-i18n';
1956
- `);let x=d.join(c,"tsconfig.json");if(f.existsSync(x))try{let b=f.readFileSync(x,"utf8");if(b.includes('"paths": {')){let u=b.replace(/"paths":\s*\{/,`"paths": {
1964
+ `);let N=d.join(c,"tsconfig.json");if(f.existsSync(N))try{let b=f.readFileSync(N,"utf8");if(b.includes('"paths": {')){let u=b.replace(/"paths":\s*\{/,`"paths": {
1957
1965
  "next-intl": ["./src/lib/mock-i18n"],
1958
- "next-intl/*": ["./src/lib/mock-i18n"],`);f.writeFileSync(x,u)}}catch{}let L=d.join(c,"src");f.existsSync(L)&&Po(L,b=>{if(!b.endsWith(".ts")&&!b.endsWith(".tsx"))return;let u=f.readFileSync(b,"utf8"),T=!1;b.endsWith("src/app/layout.tsx")&&u.includes("../providers")&&(u=u.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),T=!0),u=u.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),u=u.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),u.match(/locale\s*:\s*any/)&&(u=u.replace(/locale\s*:\s*any/g,"locale: string"),T=!0),u.match(/lang\s*:\s*any/)&&(u=u.replace(/lang\s*:\s*any/g,"lang: string"),T=!0),u.match(/requestLocale\s*:\s*any/)&&(u=u.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),T=!0),u.match(/\(locale\s*=\s*(.*)\)/)&&(u=u.replace(/\(locale\s*=\s*(.*)\)/g,"() "),T=!0),u.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(u=u.replace(/export\s+default\s+async\s+function\s+LangLayout\s*\(\s*\{\s*children\s*,\s*params\s*\}\s*:\s*LangLayoutProps\s*\)/g,"export default async function LangLayout({ children }: { children: React.ReactNode })"),T=!0),(b.endsWith("src/app/layout.tsx")||b.endsWith("src/app/sitemap.ts")||b.endsWith("src/app/robots.ts")||b.endsWith("src/components/ui/locale-switcher.tsx")||b.endsWith("src/app/(marketing)/blog/[slug]/page.tsx"))&&(u=u.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),u=u.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),u=u.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),u=u.replace(/\(l\)\s*=>/g,"(l: any) =>"),T=!0),b.endsWith("src/i18n/request.ts")&&(u=u.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),T=!0),(u.match(/locale\s*:/)||u.match(/lang\s*:/))&&(T=!0),T&&f.writeFileSync(b,u)});let oe=d.join(c,"package.json");if(f.existsSync(oe)){let b=JSON.parse(f.readFileSync(oe,"utf8"));b.dependencies&&delete b.dependencies["next-intl"],f.writeFileSync(oe,JSON.stringify(b,null,2)+`
1966
+ "next-intl/*": ["./src/lib/mock-i18n"],`);f.writeFileSync(N,u)}}catch{}let L=d.join(c,"src");f.existsSync(L)&&Co(L,b=>{if(!b.endsWith(".ts")&&!b.endsWith(".tsx"))return;let u=f.readFileSync(b,"utf8"),T=!1;b.endsWith("src/app/layout.tsx")&&u.includes("../providers")&&(u=u.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),T=!0),u=u.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),u=u.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),u.match(/locale\s*:\s*any/)&&(u=u.replace(/locale\s*:\s*any/g,"locale: string"),T=!0),u.match(/lang\s*:\s*any/)&&(u=u.replace(/lang\s*:\s*any/g,"lang: string"),T=!0),u.match(/requestLocale\s*:\s*any/)&&(u=u.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),T=!0),u.match(/\(locale\s*=\s*(.*)\)/)&&(u=u.replace(/\(locale\s*=\s*(.*)\)/g,"() "),T=!0),u.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(u=u.replace(/export\s+default\s+async\s+function\s+LangLayout\s*\(\s*\{\s*children\s*,\s*params\s*\}\s*:\s*LangLayoutProps\s*\)/g,"export default async function LangLayout({ children }: { children: React.ReactNode })"),T=!0),(b.endsWith("src/app/layout.tsx")||b.endsWith("src/app/sitemap.ts")||b.endsWith("src/app/robots.ts")||b.endsWith("src/components/ui/locale-switcher.tsx")||b.endsWith("src/app/(marketing)/blog/[slug]/page.tsx"))&&(u=u.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),u=u.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),u=u.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),u=u.replace(/\(l\)\s*=>/g,"(l: any) =>"),T=!0),b.endsWith("src/i18n/request.ts")&&(u=u.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),T=!0),(u.match(/locale\s*:/)||u.match(/lang\s*:/))&&(T=!0),T&&f.writeFileSync(b,u)});let re=d.join(c,"package.json");if(f.existsSync(re)){let b=JSON.parse(f.readFileSync(re,"utf8"));b.dependencies&&delete b.dependencies["next-intl"],f.writeFileSync(re,JSON.stringify(b,null,2)+`
1959
1967
  `)}}}}f.writeFileSync(o,JSON.stringify(n,null,2)+`
1960
- `)}function E(e){try{f.rmSync(e,{recursive:!0,force:!0})}catch{}}function ci(e,t){if(!f.existsSync(e))return;let o;try{o=JSON.parse(f.readFileSync(e,"utf8"))}catch{return}let n=!1;if(o.dependencies&&t in o.dependencies){let{[t]:r,...s}=o.dependencies;o={...o,dependencies:s},n=!0}if(o.devDependencies&&t in o.devDependencies){let{[t]:r,...s}=o.devDependencies;o={...o,devDependencies:s},n=!0}n&&f.writeFileSync(e,JSON.stringify(o,null,2)+`
1961
- `)}function Io(e,t){t.cronJobs||(E(d.join(e,"apps/web/src/app/api/cron")),E(d.join(e,"packages/queue/src/scheduled"))),t.auditLog||(E(d.join(e,"apps/web/src/app/[locale]/(app)/settings/audit-log")),E(d.join(e,"apps/web/src/app/api/audit-logs")),E(d.join(e,"apps/web/src/components/audit"))),t.apiKeys||(E(d.join(e,"apps/web/src/app/[locale]/(app)/settings/api-keys")),E(d.join(e,"apps/web/src/app/api/api-keys")),E(d.join(e,"apps/web/src/components/api-keys"))),t.webhooks||(E(d.join(e,"apps/web/src/app/[locale]/(app)/settings/webhooks")),E(d.join(e,"apps/web/src/app/api/webhooks")),E(d.join(e,"apps/web/src/components/webhooks")),E(d.join(e,"packages/webhooks"))),t.commandPalette||(E(d.join(e,"apps/web/src/components/command-palette")),E(d.join(e,"apps/web/src/app/[locale]/providers/command-palette-mount.tsx"))),t.cookieConsent||(E(d.join(e,"apps/landing-page/src/components/cookie-consent-banner.tsx")),E(d.join(e,"apps/landing-page/src/components/__tests__/cookie-consent-banner.test.tsx")),E(d.join(e,"apps/landing-page/src/lib/cookie-consent.ts")),E(d.join(e,"apps/landing-page/src/lib/__tests__/cookie-consent.test.ts")),E(d.join(e,"apps/web/src/app/api/cookie-consent"))),t.legalPages||(E(d.join(e,"apps/landing-page/src/app/[lang]/(legal)/legal")),E(d.join(e,"apps/landing-page/src/lib/legal-documents.ts")),E(d.join(e,"apps/landing-page/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(E(d.join(e,"packages/china-compliance")),E(d.join(e,"apps/landing-page/src/components/icp-footer.tsx")),E(d.join(e,"apps/landing-page/src/components/__tests__/icp-footer.test.tsx")),E(d.join(e,"apps/web/src/components/auth/wechat-login-button.tsx")),E(d.join(e,"apps/web/src/components/auth/__tests__/wechat-login-button.test.tsx")),ci(d.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import{getSchema as pi,printSchema as li}from"@mrleebo/prisma-ast";var di=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function ui(e){return e.type==="comment"&&e.text.trim().startsWith("///")}function mi(e){let t=di.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 gi(e,t){for(let o=t-1;o>=0;o--){let n=e[o];if(n.type==="comment"){let r=mi(n.text);if(r)return{annIndex:o,parsed:r};continue}break}return null}function Zt(e,t){let o=pi(e),n=new Set;for(let c=0;c<o.list.length;c++){if(o.list[c].type!=="model")continue;let l=gi(o.list,c);if(!l)continue;let m=t[l.parsed.flag];if(m!==void 0&&l.parsed.values.includes(m))n.add(l.annIndex);else{n.add(c);for(let x=c-1;x>=0;x--){let L=o.list[x];if(L.type==="comment"&&ui(L)){n.add(x);continue}break}let k=o.list[c+1];k&&k.type==="break"&&n.add(c+1)}}let r=o.list.filter((c,a)=>!n.has(a)),s=[];for(let c of r){let a=s[s.length-1];c.type==="break"&&a&&a.type==="break"||s.push(c)}return li({type:"schema",list:s})}import de from"fs";import en from"path";var xt=[{id:"qstash",name:"Upstash QStash",region:"both",envVars:["QSTASH_TOKEN","QSTASH_CURRENT_SIGNING_KEY","QSTASH_NEXT_SIGNING_KEY"],docs:"https://upstash.com/docs/qstash",description:"Serverless HTTP-based queue"},{id:"bullmq",name:"BullMQ",region:"both",envVars:["REDIS_URL"],docs:"https://docs.bullmq.io",description:"Redis-backed job queue"},{id:"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 Ao(e){return xt.find(t=>t.id===e)}var bp=xt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function wo(e){return de.existsSync(e)?de.readFileSync(e,"utf-8"):null}function fi(e,t){let o=en.join(e,".env.example"),n=wo(o);if(n===null)return;let r=`# Queue: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1962
- `);de.appendFileSync(o,s)}function yi(e,t,o){let n=en.join(e,".env.example"),r=wo(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?de.writeFileSync(n,r.replace(s,`${t}="${o}"`)):de.appendFileSync(n,`${t}="${o}"
1963
- `)}async function Ro(e,t,o){let n=en.join(e,"packages","queue");if(t==="none"){de.existsSync(n)&&de.rmSync(n,{recursive:!0,force:!0});return}let r=Ao(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${xt.map(s=>s.id).join(", ")}`);de.existsSync(n)&&(fi(e,r),yi(e,"QUEUE_PROVIDER",t))}import ue from"fs";import tn 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 ko(e){return Nt.find(t=>t.id===e)}var Rp=Nt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function xo(e){return ue.existsSync(e)?ue.readFileSync(e,"utf-8"):null}function Si(e,t){let o=tn.join(e,".env.example"),n=xo(o);if(n===null)return;let r=`# Search: ${t.name}`;if(n.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1964
- `);ue.appendFileSync(o,s)}function hi(e,t,o){let n=tn.join(e,".env.example"),r=xo(n);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?ue.writeFileSync(n,r.replace(s,`${t}="${o}"`)):ue.appendFileSync(n,`${t}="${o}"
1965
- `)}async function No(e,t,o){let n=tn.join(e,"packages","search");if(t==="none"){ue.existsSync(n)&&ue.rmSync(n,{recursive:!0,force:!0});return}let r=ko(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${Nt.map(s=>s.id).join(", ")}`);ue.existsSync(n)&&(Si(e,r),hi(e,"SEARCH_PROVIDER",t))}import me from"fs";import ke from"path";function Ei(e){let t=[ke.join(e,"packages","db"),ke.join(e,"apps","web")];for(let o of t){let n=ke.join(o,"prisma","schema.prisma");if(me.existsSync(n))return{packageDir:o,seedPath:ke.join(o,"prisma","seed.ts"),packageJsonPath:ke.join(o,"package.json")}}return null}function vi(e){try{let t=me.readFileSync(e,"utf8"),o=new Set,n=/^\s*model\s+(\w+)\s*\{/gm,r=n.exec(t);for(;r;)o.add(r[1]),r=n.exec(t);return o}catch{return new Set}}function _i(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
1968
+ `)}function E(e){try{f.rmSync(e,{recursive:!0,force:!0})}catch{}}function ps(e,t){if(!f.existsSync(e))return;let o;try{o=JSON.parse(f.readFileSync(e,"utf8"))}catch{return}let n=!1;if(o.dependencies&&t in o.dependencies){let{[t]:r,...i}=o.dependencies;o={...o,dependencies:i},n=!0}if(o.devDependencies&&t in o.devDependencies){let{[t]:r,...i}=o.devDependencies;o={...o,devDependencies:i},n=!0}n&&f.writeFileSync(e,JSON.stringify(o,null,2)+`
1969
+ `)}function Ao(e,t){t.cronJobs||(E(d.join(e,"apps/web/src/app/api/cron")),E(d.join(e,"packages/integrations/queue/src/scheduled"))),t.auditLog||(E(d.join(e,"apps/web/src/app/[locale]/(app)/settings/audit-log")),E(d.join(e,"apps/web/src/app/api/audit-logs")),E(d.join(e,"apps/web/src/components/audit"))),t.apiKeys||(E(d.join(e,"apps/web/src/app/[locale]/(app)/settings/api-keys")),E(d.join(e,"apps/web/src/app/api/api-keys")),E(d.join(e,"apps/web/src/components/api-keys"))),t.webhooks||(E(d.join(e,"apps/web/src/app/[locale]/(app)/settings/webhooks")),E(d.join(e,"apps/web/src/app/api/webhooks")),E(d.join(e,"apps/web/src/components/webhooks")),E(d.join(e,"packages/webhooks"))),t.commandPalette||(E(d.join(e,"apps/web/src/components/command-palette")),E(d.join(e,"apps/web/src/app/[locale]/providers/command-palette-mount.tsx"))),t.cookieConsent||(E(d.join(e,"apps/landing-page/src/components/cookie-consent-banner.tsx")),E(d.join(e,"apps/landing-page/src/components/__tests__/cookie-consent-banner.test.tsx")),E(d.join(e,"apps/landing-page/src/lib/cookie-consent.ts")),E(d.join(e,"apps/landing-page/src/lib/__tests__/cookie-consent.test.ts")),E(d.join(e,"apps/web/src/app/api/cookie-consent"))),t.legalPages||(E(d.join(e,"apps/landing-page/src/app/[lang]/(legal)/legal")),E(d.join(e,"apps/landing-page/src/lib/legal-documents.ts")),E(d.join(e,"apps/landing-page/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(E(d.join(e,"packages/china-compliance")),E(d.join(e,"apps/landing-page/src/components/icp-footer.tsx")),E(d.join(e,"apps/landing-page/src/components/__tests__/icp-footer.test.tsx")),E(d.join(e,"apps/web/src/components/auth/wechat-login-button.tsx")),E(d.join(e,"apps/web/src/components/auth/__tests__/wechat-login-button.test.tsx")),ps(d.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import{getSchema as ls,printSchema as ds}from"@mrleebo/prisma-ast";var us=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function ms(e){return e.type==="comment"&&e.text.trim().startsWith("///")}function gs(e){let t=us.exec(e.trim());if(!t)return null;let[,o,n]=t,r=n.split("|").map(i=>i.trim()).filter(i=>i.length>0);return{flag:o,values:r}}function fs(e,t){for(let o=t-1;o>=0;o--){let n=e[o];if(n.type==="comment"){let r=gs(n.text);if(r)return{annIndex:o,parsed:r};continue}break}return null}function tn(e,t){let o=ls(e),n=new Set;for(let c=0;c<o.list.length;c++){if(o.list[c].type!=="model")continue;let l=fs(o.list,c);if(!l)continue;let m=t[l.parsed.flag];if(m!==void 0&&l.parsed.values.includes(m))n.add(l.annIndex);else{n.add(c);for(let N=c-1;N>=0;N--){let L=o.list[N];if(L.type==="comment"&&ms(L)){n.add(N);continue}break}let x=o.list[c+1];x&&x.type==="break"&&n.add(c+1)}}let r=o.list.filter((c,a)=>!n.has(a)),i=[];for(let c of r){let a=i[i.length-1];c.type==="break"&&a&&a.type==="break"||i.push(c)}return ds({type:"schema",list:i})}import ue from"fs";import nn from"path";var Tt=[{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 wo(e){return Tt.find(t=>t.id===e)}var Pp=Tt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ro(e){return ue.existsSync(e)?ue.readFileSync(e,"utf-8"):null}function ys(e,t){let o=nn.join(e,".env.example"),n=Ro(o);if(n===null)return;let r=`# Queue: ${t.name}`;if(n.includes(r))return;let i=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(s=>`${s}=""`),""].join(`
1970
+ `);ue.appendFileSync(o,i)}function Ss(e,t,o){let n=nn.join(e,".env.example"),r=Ro(n);if(r===null)return;let i=new RegExp(`^${t}=.*$`,"m");i.test(r)?ue.writeFileSync(n,r.replace(i,`${t}="${o}"`)):ue.appendFileSync(n,`${t}="${o}"
1971
+ `)}async function ko(e,t,o){let n=nn.join(e,"packages","queue");if(t==="none"){ue.existsSync(n)&&ue.rmSync(n,{recursive:!0,force:!0});return}let r=wo(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${Tt.map(i=>i.id).join(", ")}`);ue.existsSync(n)&&(ys(e,r),Ss(e,"QUEUE_PROVIDER",t))}import me from"fs";import on from"path";var Ot=[{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 xo(e){return Ot.find(t=>t.id===e)}var kp=Ot.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function No(e){return me.existsSync(e)?me.readFileSync(e,"utf-8"):null}function hs(e,t){let o=on.join(e,".env.example"),n=No(o);if(n===null)return;let r=`# Search: ${t.name}`;if(n.includes(r))return;let i=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(s=>`${s}=""`),""].join(`
1972
+ `);me.appendFileSync(o,i)}function Es(e,t,o){let n=on.join(e,".env.example"),r=No(n);if(r===null)return;let i=new RegExp(`^${t}=.*$`,"m");i.test(r)?me.writeFileSync(n,r.replace(i,`${t}="${o}"`)):me.appendFileSync(n,`${t}="${o}"
1973
+ `)}async function To(e,t,o){let n=on.join(e,"packages","search");if(t==="none"){me.existsSync(n)&&me.rmSync(n,{recursive:!0,force:!0});return}let r=xo(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${Ot.map(i=>i.id).join(", ")}`);me.existsSync(n)&&(hs(e,r),Es(e,"SEARCH_PROVIDER",t))}import ge from"fs";import xe from"path";function vs(e){let t=[xe.join(e,"packages","db"),xe.join(e,"apps","web")];for(let o of t){let n=xe.join(o,"prisma","schema.prisma");if(ge.existsSync(n))return{packageDir:o,seedPath:xe.join(o,"prisma","seed.ts"),packageJsonPath:xe.join(o,"package.json")}}return null}function _s(e){try{let t=ge.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 bs(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
1966
1974
  const admin = await prisma.user.create({
1967
1975
  data: {
1968
1976
  clerkId: "user_mock_admin",
@@ -1993,7 +2001,7 @@ export { default } from './mock-i18n';
1993
2001
  console.log("\\u2713 Created admin user:", admin.email);
1994
2002
  } catch (err) {
1995
2003
  console.warn("\\u26A0 Admin user creation skipped:", (err as Error).message);
1996
- }`}function bi(e,t){let o=t.has("Tenant"),n=t.has("User"),r=t.has("Project"),s=_i(e,n),i=o?` let tenants: Array<{ id: string; name: string }> = [];
2004
+ }`}function Ps(e,t){let o=t.has("Tenant"),n=t.has("User"),r=t.has("Project"),i=bs(e,n),s=o?` let tenants: Array<{ id: string; name: string }> = [];
1997
2005
  try {
1998
2006
  tenants = await Promise.all([
1999
2007
  prisma.tenant.create({
@@ -2043,10 +2051,10 @@ async function main(): Promise<void> {
2043
2051
  console.log("\\uD83C\\uDF31 Seeding database...");
2044
2052
 
2045
2053
  // --- Tenants ---------------------------------------------------------
2046
- ${i}
2054
+ ${s}
2047
2055
 
2048
2056
  // --- Admin user ------------------------------------------------------
2049
- ${s}
2057
+ ${i}
2050
2058
 
2051
2059
  // --- Sample projects per tenant --------------------------------------
2052
2060
  ${c}
@@ -2062,12 +2070,12 @@ main()
2062
2070
  .finally(async () => {
2063
2071
  await prisma.$disconnect();
2064
2072
  });
2065
- `}function Pi(e){if(me.existsSync(e))try{let t=me.readFileSync(e,"utf8"),o=JSON.parse(t),n=o.scripts??{},r=!1;n["db:seed"]||(n["db:seed"]="prisma db seed",r=!0);let s=o.prisma??{};if(s.seed||(s.seed="tsx prisma/seed.ts",r=!0),!r)return;let i={...o,scripts:n,prisma:s};me.writeFileSync(e,JSON.stringify(i,null,2)+`
2066
- `)}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 To(e,t){let o=Ei(e);if(o)try{let n=ke.join(o.packageDir,"prisma","schema.prisma"),r=vi(n),s=bi(t,r),i=ke.dirname(o.seedPath);me.existsSync(i)||me.mkdirSync(i,{recursive:!0}),me.writeFileSync(o.seedPath,s),Pi(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 ge from"fs";import xe from"path";var Tt=[{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:""}],jp=Tt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Oo(e){return Tt.find(t=>t.id===e)}var Ci="@nebutra/sms",Ii={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 nn(e,t){ge.mkdirSync(xe.dirname(e),{recursive:!0}),ge.writeFileSync(e,t)}function Ai(e,t){let o=xe.join(e,".env.example");ge.existsSync(o)?ge.appendFileSync(o,`
2067
- `+t):ge.writeFileSync(o,t)}function wi(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2073
+ `}function Cs(e){if(ge.existsSync(e))try{let t=ge.readFileSync(e,"utf8"),o=JSON.parse(t),n=o.scripts??{},r=!1;n["db:seed"]||(n["db:seed"]="prisma db seed",r=!0);let i=o.prisma??{};if(i.seed||(i.seed="tsx prisma/seed.ts",r=!0),!r)return;let s={...o,scripts:n,prisma:i};ge.writeFileSync(e,JSON.stringify(s,null,2)+`
2074
+ `)}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 Oo(e,t){let o=vs(e);if(o)try{let n=xe.join(o.packageDir,"prisma","schema.prisma"),r=_s(n),i=Ps(t,r),s=xe.dirname(o.seedPath);ge.existsSync(s)||ge.mkdirSync(s,{recursive:!0}),ge.writeFileSync(o.seedPath,i),Cs(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 fe from"fs";import Ne from"path";var Ut=[{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:""}],Dp=Ut.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Uo(e){return Ut.find(t=>t.id===e)}var Is="@nebutra/sms",As={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 rn(e,t){fe.mkdirSync(Ne.dirname(e),{recursive:!0}),fe.writeFileSync(e,t)}function ws(e,t){let o=Ne.join(e,".env.example");fe.existsSync(o)?fe.appendFileSync(o,`
2075
+ `+t):fe.writeFileSync(o,t)}function Rs(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2068
2076
  `);return`${t}
2069
2077
  ${o}
2070
- `}var Ri=`/**
2078
+ `}var ks=`/**
2071
2079
  * Inputs for the \`sendSms\` wrapper. Keep this surface portable across
2072
2080
  * providers \u2014 provider-specific options belong in the wrapper itself.
2073
2081
  */
@@ -2087,8 +2095,8 @@ export interface SendSmsResult {
2087
2095
  provider: string;
2088
2096
  raw?: unknown;
2089
2097
  }
2090
- `;function ki(){return`import twilio from "twilio";
2091
- import type { SendSmsInput, SendSmsResult } from "./types.js";
2098
+ `;function xs(){return`import twilio from "twilio";
2099
+ import type { SendSmsInput, SendSmsResult } from "./types";
2092
2100
 
2093
2101
  let client: ReturnType<typeof twilio> | null = null;
2094
2102
 
@@ -2121,9 +2129,9 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2121
2129
  return { messageId: message.sid, provider: "twilio", raw: message };
2122
2130
  }
2123
2131
 
2124
- export type { SendSmsInput, SendSmsResult } from "./types.js";
2125
- `}function xi(){return`import messagebird from "messagebird";
2126
- import type { SendSmsInput, SendSmsResult } from "./types.js";
2132
+ export type { SendSmsInput, SendSmsResult } from "./types";
2133
+ `}function Ns(){return`import messagebird from "messagebird";
2134
+ import type { SendSmsInput, SendSmsResult } from "./types";
2127
2135
 
2128
2136
  let client: ReturnType<typeof messagebird> | null = null;
2129
2137
 
@@ -2159,9 +2167,9 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2159
2167
  });
2160
2168
  }
2161
2169
 
2162
- export type { SendSmsInput, SendSmsResult } from "./types.js";
2163
- `}function Ni(){return`import plivo from "plivo";
2164
- import type { SendSmsInput, SendSmsResult } from "./types.js";
2170
+ export type { SendSmsInput, SendSmsResult } from "./types";
2171
+ `}function Ts(){return`import plivo from "plivo";
2172
+ import type { SendSmsInput, SendSmsResult } from "./types";
2165
2173
 
2166
2174
  let client: InstanceType<typeof plivo.Client> | null = null;
2167
2175
 
@@ -2198,10 +2206,10 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2198
2206
  };
2199
2207
  }
2200
2208
 
2201
- export type { SendSmsInput, SendSmsResult } from "./types.js";
2202
- `}function Ti(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2209
+ export type { SendSmsInput, SendSmsResult } from "./types";
2210
+ `}function Os(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2203
2211
  import * as $OpenApi from "@alicloud/openapi-client";
2204
- import type { SendSmsInput, SendSmsResult } from "./types.js";
2212
+ import type { SendSmsInput, SendSmsResult } from "./types";
2205
2213
 
2206
2214
  let client: Dysmsapi | null = null;
2207
2215
 
@@ -2247,9 +2255,9 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2247
2255
  };
2248
2256
  }
2249
2257
 
2250
- export type { SendSmsInput, SendSmsResult } from "./types.js";
2251
- `}function Oi(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2252
- import type { SendSmsInput, SendSmsResult } from "./types.js";
2258
+ export type { SendSmsInput, SendSmsResult } from "./types";
2259
+ `}function Us(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2260
+ import type { SendSmsInput, SendSmsResult } from "./types";
2253
2261
 
2254
2262
  const SmsClient = tencentcloud.sms.v20210111.Client;
2255
2263
  type SmsClientInstance = InstanceType<typeof SmsClient>;
@@ -2312,10 +2320,10 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2312
2320
  };
2313
2321
  }
2314
2322
 
2315
- export type { SendSmsInput, SendSmsResult } from "./types.js";
2316
- `}function Ui(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2323
+ export type { SendSmsInput, SendSmsResult } from "./types";
2324
+ `}function Ls(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2317
2325
  import Yunpian from "yunpian-nodejs-sdk";
2318
- import type { SendSmsInput, SendSmsResult } from "./types.js";
2326
+ import type { SendSmsInput, SendSmsResult } from "./types";
2319
2327
 
2320
2328
  let client: { sms: { single_send(opts: unknown): Promise<unknown>; tpl_single_send(opts: unknown): Promise<unknown> } } | null =
2321
2329
  null;
@@ -2364,14 +2372,14 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2364
2372
  return { provider: "yunpian", raw };
2365
2373
  }
2366
2374
 
2367
- export type { SendSmsInput, SendSmsResult } from "./types.js";
2368
- `}function Li(e){switch(e){case"twilio":return ki();case"messagebird":return xi();case"plivo":return Ni();case"aliyun-sms":return Ti();case"tencent-sms":return Oi();case"yunpian":return Ui();case"none":return`export {};
2369
- `}}function Mi(e){let t={};for(let n of e.pkgs??[]){let r=Ii[n];r&&(t[n]=r)}let o={name:Ci,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)+`
2370
- `}async function Uo(e,t,o="global"){if(t==="none")return;let n=Oo(t);if(!n)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${Tt.map(i=>i.id).join(", ")}`);let r=xe.join(e,"packages","sms");if(!ge.existsSync(r))return;let s=xe.join(r,"src");ge.existsSync(s)&&ge.rmSync(s,{recursive:!0,force:!0});try{nn(xe.join(r,"package.json"),Mi(n)),nn(xe.join(s,"types.ts"),Ri),nn(xe.join(s,"index.ts"),Li(n.id)),Ai(e,wi(n))}catch(i){throw console.error(`Failed to apply SMS selection "${t}":`,i),new Error(`SMS scaffold for "${t}" failed \u2014 see stderr for details.`)}}import Te from"fs";import Ne from"path";var mt=[{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 on(e){let t=e==="supabase"?"supabase-storage":e;return mt.some(o=>o.id===t)?t:void 0}function Lo(e){let t=on(e);return t?mt.find(o=>o.id===t):void 0}var Yp=mt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Oe="@nebutra/storage";function rn(e,t){Te.mkdirSync(Ne.dirname(e),{recursive:!0}),Te.writeFileSync(e,t)}function ji(e,t){let o=Ne.join(e,".env.example");Te.existsSync(o)?Te.appendFileSync(o,`
2371
- `+t):Te.writeFileSync(o,t)}function Fi(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2375
+ export type { SendSmsInput, SendSmsResult } from "./types";
2376
+ `}function Ms(e){switch(e){case"twilio":return xs();case"messagebird":return Ns();case"plivo":return Ts();case"aliyun-sms":return Os();case"tencent-sms":return Us();case"yunpian":return Ls();case"none":return`export {};
2377
+ `}}function Fs(e){let t={};for(let n of e.pkgs??[]){let r=As[n];r&&(t[n]=r)}let o={name:Is,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)+`
2378
+ `}async function Lo(e,t,o="global"){if(t==="none")return;let n=Uo(t);if(!n)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${Ut.map(s=>s.id).join(", ")}`);let r=Ne.join(e,"packages","sms");if(!fe.existsSync(r))return;let i=Ne.join(r,"src");fe.existsSync(i)&&fe.rmSync(i,{recursive:!0,force:!0});try{rn(Ne.join(r,"package.json"),Fs(n)),rn(Ne.join(i,"types.ts"),ks),rn(Ne.join(i,"index.ts"),Ms(n.id)),ws(e,Rs(n))}catch(s){throw console.error(`Failed to apply SMS selection "${t}":`,s),new Error(`SMS scaffold for "${t}" failed \u2014 see stderr for details.`)}}import Oe from"fs";import Te from"path";var gt=[{id:"r2",name:"Cloudflare R2",region:"global",envVars:["R2_ACCOUNT_ID","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY","R2_BUCKET"],docs:"https://developers.cloudflare.com/r2/api/s3/api/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"s3",name:"AWS S3",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_S3_REGION","S3_BUCKET"],docs:"https://docs.aws.amazon.com/s3/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"supabase-storage",name:"Supabase Storage",region:"global",envVars:["SUPABASE_URL","SUPABASE_SERVICE_ROLE_KEY","SUPABASE_BUCKET"],docs:"https://supabase.com/docs/guides/storage",pkg:"@supabase/supabase-js",pkgVersion:"^2.45.4"},{id:"aliyun-oss",name:"\u963F\u91CC\u4E91 OSS",region:"cn",envVars:["ALIYUN_OSS_ACCESS_KEY","ALIYUN_OSS_ACCESS_SECRET","ALIYUN_OSS_REGION","ALIYUN_OSS_BUCKET"],docs:"https://help.aliyun.com/product/31815.html",pkg:"ali-oss",pkgVersion:"^6.21.0"},{id:"tencent-cos",name:"\u817E\u8BAF\u4E91 COS",region:"cn",envVars:["TENCENT_COS_SECRET_ID","TENCENT_COS_SECRET_KEY","TENCENT_COS_BUCKET","TENCENT_COS_REGION"],docs:"https://cloud.tencent.com/document/product/436",pkg:"cos-nodejs-sdk-v5",pkgVersion:"^2.13.7"},{id:"qiniu",name:"\u4E03\u725B\u4E91 Kodo",region:"cn",envVars:["QINIU_ACCESS_KEY","QINIU_SECRET_KEY","QINIU_BUCKET","QINIU_DOMAIN"],docs:"https://developer.qiniu.com/kodo",pkg:"qiniu",pkgVersion:"^7.14.0"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function sn(e){let t=e==="supabase"?"supabase-storage":e;return gt.some(o=>o.id===t)?t:void 0}function Mo(e){let t=sn(e);return t?gt.find(o=>o.id===t):void 0}var Yp=gt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Ue="@nebutra/storage";function an(e,t){Oe.mkdirSync(Te.dirname(e),{recursive:!0}),Oe.writeFileSync(e,t)}function Ds(e,t){let o=Te.join(e,".env.example");Oe.existsSync(o)?Oe.appendFileSync(o,`
2379
+ `+t):Oe.writeFileSync(o,t)}function js(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
2372
2380
  `);return`${t}
2373
2381
  ${o}
2374
- `}var Di=`/**
2382
+ `}var Ks=`/**
2375
2383
  * Inputs for the \`uploadFile\` wrapper. Keep this surface portable across
2376
2384
  * providers \u2014 provider-specific options belong in the wrapper itself.
2377
2385
  */
@@ -2397,8 +2405,8 @@ export interface SignedUrlOptions {
2397
2405
  operation?: "get" | "put";
2398
2406
  contentType?: string;
2399
2407
  }
2400
- `;function Ki(){return`/**
2401
- * @${Oe.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
2408
+ `;function Vs(){return`/**
2409
+ * @${Ue.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
2402
2410
  *
2403
2411
  * Docs: https://developers.cloudflare.com/r2/api/s3/api/
2404
2412
  */
@@ -2413,7 +2421,7 @@ import type {
2413
2421
  SignedUrlOptions,
2414
2422
  UploadFileInput,
2415
2423
  UploadFileResult,
2416
- } from "./types.js";
2424
+ } from "./types";
2417
2425
 
2418
2426
  const accountId = process.env.R2_ACCOUNT_ID;
2419
2427
  const accessKeyId = process.env.R2_ACCESS_KEY_ID;
@@ -2460,9 +2468,9 @@ export async function getSignedUrl(
2460
2468
  return awsGetSignedUrl(client, command, { expiresIn });
2461
2469
  }
2462
2470
 
2463
- export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2464
- `}function Vi(){return`/**
2465
- * @${Oe.slice(1)} \u2014 AWS S3 wrapper.
2471
+ export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2472
+ `}function Bs(){return`/**
2473
+ * @${Ue.slice(1)} \u2014 AWS S3 wrapper.
2466
2474
  *
2467
2475
  * Docs: https://docs.aws.amazon.com/s3/
2468
2476
  */
@@ -2477,7 +2485,7 @@ import type {
2477
2485
  SignedUrlOptions,
2478
2486
  UploadFileInput,
2479
2487
  UploadFileResult,
2480
- } from "./types.js";
2488
+ } from "./types";
2481
2489
 
2482
2490
  const region = process.env.AWS_S3_REGION;
2483
2491
  const bucket = process.env.S3_BUCKET;
@@ -2525,9 +2533,9 @@ export async function getSignedUrl(
2525
2533
  return awsGetSignedUrl(client, command, { expiresIn });
2526
2534
  }
2527
2535
 
2528
- export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2529
- `}function Bi(){return`/**
2530
- * @${Oe.slice(1)} \u2014 Supabase Storage wrapper.
2536
+ export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2537
+ `}function $s(){return`/**
2538
+ * @${Ue.slice(1)} \u2014 Supabase Storage wrapper.
2531
2539
  *
2532
2540
  * Docs: https://supabase.com/docs/guides/storage
2533
2541
  */
@@ -2537,7 +2545,7 @@ import type {
2537
2545
  SignedUrlOptions,
2538
2546
  UploadFileInput,
2539
2547
  UploadFileResult,
2540
- } from "./types.js";
2548
+ } from "./types";
2541
2549
 
2542
2550
  const url = process.env.SUPABASE_URL;
2543
2551
  const serviceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY;
@@ -2588,9 +2596,9 @@ export async function getSignedUrl(
2588
2596
  return data.signedUrl;
2589
2597
  }
2590
2598
 
2591
- export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2592
- `}function Yi(){return`/**
2593
- * @${Oe.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2599
+ export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2600
+ `}function Ys(){return`/**
2601
+ * @${Ue.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2594
2602
  *
2595
2603
  * Docs: https://help.aliyun.com/product/31815.html
2596
2604
  */
@@ -2600,7 +2608,7 @@ import type {
2600
2608
  SignedUrlOptions,
2601
2609
  UploadFileInput,
2602
2610
  UploadFileResult,
2603
- } from "./types.js";
2611
+ } from "./types";
2604
2612
 
2605
2613
  const accessKeyId = process.env.ALIYUN_OSS_ACCESS_KEY;
2606
2614
  const accessKeySecret = process.env.ALIYUN_OSS_ACCESS_SECRET;
@@ -2635,9 +2643,9 @@ export async function getSignedUrl(
2635
2643
  });
2636
2644
  }
2637
2645
 
2638
- export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2639
- `}function $i(){return`/**
2640
- * @${Oe.slice(1)} \u2014 \u817E\u8BAF\u4E91 COS wrapper via cos-nodejs-sdk-v5.
2646
+ export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2647
+ `}function qs(){return`/**
2648
+ * @${Ue.slice(1)} \u2014 \u817E\u8BAF\u4E91 COS wrapper via cos-nodejs-sdk-v5.
2641
2649
  *
2642
2650
  * Docs: https://cloud.tencent.com/document/product/436
2643
2651
  */
@@ -2647,7 +2655,7 @@ import type {
2647
2655
  SignedUrlOptions,
2648
2656
  UploadFileInput,
2649
2657
  UploadFileResult,
2650
- } from "./types.js";
2658
+ } from "./types";
2651
2659
 
2652
2660
  const secretId = process.env.TENCENT_COS_SECRET_ID;
2653
2661
  const secretKey = process.env.TENCENT_COS_SECRET_KEY;
@@ -2690,9 +2698,9 @@ export async function getSignedUrl(
2690
2698
  return url as unknown as string;
2691
2699
  }
2692
2700
 
2693
- export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2694
- `}function qi(){return`/**
2695
- * @${Oe.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2701
+ export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2702
+ `}function Gs(){return`/**
2703
+ * @${Ue.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2696
2704
  *
2697
2705
  * Docs: https://developer.qiniu.com/kodo
2698
2706
  */
@@ -2702,7 +2710,7 @@ import type {
2702
2710
  SignedUrlOptions,
2703
2711
  UploadFileInput,
2704
2712
  UploadFileResult,
2705
- } from "./types.js";
2713
+ } from "./types";
2706
2714
 
2707
2715
  const accessKey = process.env.QINIU_ACCESS_KEY;
2708
2716
  const secretKey = process.env.QINIU_SECRET_KEY;
@@ -2758,10 +2766,10 @@ export async function getSignedUrl(
2758
2766
  return bucketManager.privateDownloadUrl(domain, key, deadline);
2759
2767
  }
2760
2768
 
2761
- export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2762
- `}function Gi(e){switch(e){case"r2":return Ki();case"s3":return Vi();case"supabase-storage":return Bi();case"aliyun-oss":return Yi();case"tencent-cos":return $i();case"qiniu":return qi();case"none":return`export {};
2763
- `}}function Wi(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:Oe,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)+`
2764
- `}async function Mo(e,t,o){if(t==="none")return;let n=Lo(t);if(!n)throw new Error(`Unknown storage provider "${t}". Valid ids: ${mt.map(i=>i.id).join(", ")}`);let r=Ne.join(e,"packages","storage"),s=Ne.join(r,"src");Te.existsSync(s)&&Te.rmSync(s,{recursive:!0,force:!0}),rn(Ne.join(r,"package.json"),Wi(n)),rn(Ne.join(s,"types.ts"),Di),rn(Ne.join(s,"index.ts"),Gi(n.id)),ji(e,Fi(n))}function fe(e,t){if(e===void 0)return t;let o=String(e).trim().toLowerCase();return o==="true"||o==="1"||o==="yes"||o==="on"?!0:o==="false"||o==="0"||o==="no"||o==="off"?!1:t}function jo(e,t){let o=t==="cn";return{cronJobs:fe(e.cronJobs,!0),auditLog:fe(e.auditLog,!0),apiKeys:fe(e.apiKeys,!0),webhooks:fe(e.webhooks,!0),commandPalette:fe(e.commandPalette,!0),cookieConsent:fe(e.cookieConsent,!0),legalPages:fe(e.legalPages,!0),chinaCompliance:fe(e.chinaCompliance,o)}}var Ot=[{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 Fo(e){return Ot.find(t=>t.id===e)}var zp=Ot.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Do(e,t,o="global"){let n=Fo(t);if(!n)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Ot.map(r=>r.id).join(", ")}`);if(n.id==="none"){Y(e,"webhooks");return}n.envVars.length>0&&W(e,{category:"Webhooks",name:n.name,envVars:n.envVars,docs:n.docs}),H(e,"WEBHOOKS_PROVIDER",n.id)}import Ue from"fs";import gt from"path";function Hi(e){return`import Link from "next/link";
2769
+ export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2770
+ `}function Ws(e){switch(e){case"r2":return Vs();case"s3":return Bs();case"supabase-storage":return $s();case"aliyun-oss":return Ys();case"tencent-cos":return qs();case"qiniu":return Gs();case"none":return`export {};
2771
+ `}}function Hs(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),(e.id==="r2"||e.id==="s3")&&(t["@aws-sdk/s3-request-presigner"]="^3.658.0");let o={name:Ue,version:"0.1.0",private:!0,description:`Object storage via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(o,null,2)+`
2772
+ `}async function Fo(e,t,o){if(t==="none")return;let n=Mo(t);if(!n)throw new Error(`Unknown storage provider "${t}". Valid ids: ${gt.map(s=>s.id).join(", ")}`);let r=Te.join(e,"packages","storage"),i=Te.join(r,"src");Oe.existsSync(i)&&Oe.rmSync(i,{recursive:!0,force:!0}),an(Te.join(r,"package.json"),Hs(n)),an(Te.join(i,"types.ts"),Ks),an(Te.join(i,"index.ts"),Ws(n.id)),Ds(e,js(n))}function ye(e,t){if(e===void 0)return t;let o=String(e).trim().toLowerCase();return o==="true"||o==="1"||o==="yes"||o==="on"?!0:o==="false"||o==="0"||o==="no"||o==="off"?!1:t}function Do(e,t){let o=t==="cn";return{cronJobs:ye(e.cronJobs,!0),auditLog:ye(e.auditLog,!0),apiKeys:ye(e.apiKeys,!0),webhooks:ye(e.webhooks,!0),commandPalette:ye(e.commandPalette,!0),cookieConsent:ye(e.cookieConsent,!0),legalPages:ye(e.legalPages,!0),chinaCompliance:ye(e.chinaCompliance,o)}}var Lt=[{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 jo(e){return Lt.find(t=>t.id===e)}var Jp=Lt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Ko(e,t,o="global"){let n=jo(t);if(!n)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Lt.map(r=>r.id).join(", ")}`);if(n.id==="none"){Y(e,"webhooks");return}n.envVars.length>0&&H(e,{category:"Webhooks",name:n.name,envVars:n.envVars,docs:n.docs}),X(e,"WEBHOOKS_PROVIDER",n.id)}import Le from"fs";import ft from"path";function Xs(e){return`import Link from "next/link";
2765
2773
 
2766
2774
  export default function WelcomePage() {
2767
2775
  const projectName = ${JSON.stringify(e)};
@@ -2870,21 +2878,21 @@ function Step({
2870
2878
  </li>
2871
2879
  );
2872
2880
  }
2873
- `}function Xi(e={}){return`
2881
+ `}function zs(e={}){return`
2874
2882
  ## What you can do next
2875
2883
 
2876
- ${[e.apiKeys===!1?"- Manage API keys at `/settings/api-keys` (disabled \u2014 re-enable with `--api-keys=true`)":"- Manage API keys at `/settings/api-keys`",e.auditLog===!1?"- View audit log at `/settings/audit-log` (disabled \u2014 re-enable with `--audit-log=true`)":"- View audit log at `/settings/audit-log`","- Configure webhooks at `/settings/webhooks`",e.commandPalette===!1?"- Press \u2318K to open the command palette (disabled \u2014 re-enable with `--command-palette=true`)":"- Press \u2318K to open the command palette","- Edit notification preferences at `/settings/notifications`","- Export your data at `/settings/account/export`","- For China deployments, see `packages/china-compliance/README.md`"].join(`
2884
+ ${[e.apiKeys===!1?"- Manage API keys at `/settings/api-keys` (disabled \u2014 re-enable with `--api-keys=true`)":"- Manage API keys at `/settings/api-keys`",e.auditLog===!1?"- View audit log at `/settings/audit-log` (disabled \u2014 re-enable with `--audit-log=true`)":"- View audit log at `/settings/audit-log`","- Configure webhooks at `/settings/webhooks`",e.commandPalette===!1?"- Press \u2318K to open the command palette (disabled \u2014 re-enable with `--command-palette=true`)":"- Press \u2318K to open the command palette","- Edit notification preferences at `/settings/notifications`","- Export your data at `/settings/account/export`","- For China deployments, see `packages/ops/china-compliance/README.md`"].join(`
2877
2885
  `)}
2878
- `}function zi(e=[]){return e.length===0?"":`
2886
+ `}function Js(e=[]){return e.length===0?"":`
2879
2887
  ## Production readiness holds
2880
2888
 
2881
2889
  Do not enable these in production until you replace stubs, add provider credentials, and verify the integration contract:
2882
2890
 
2883
- ${e.map(o=>{let n=ze(o.status);return`- ${o.flag}=${o.provider} ${n} \u2014 ${se(o.status)}`}).join(`
2891
+ ${e.map(o=>{let n=Je(o.status);return`- ${o.flag}=${o.provider} ${n} \u2014 ${se(o.status)}`}).join(`
2884
2892
  `)}
2885
2893
 
2886
2894
  Review the package readiness matrix before handoff: [docs/package-status.md](docs/package-status.md)
2887
- `}function Ji(e,t,o=[],n={}){return`# Next steps \u2014 ${e}
2895
+ `}function Qs(e,t,o=[],n={}){return`# Next steps \u2014 ${e}
2888
2896
 
2889
2897
  Region: ${t}
2890
2898
 
@@ -2910,33 +2918,42 @@ Your AI-native SaaS scaffold is ready. Complete these four steps to go from temp
2910
2918
  \`\`\`
2911
2919
 
2912
2920
  After setup, delete the welcome route at \`apps/web/src/app/[locale]/welcome/\`.
2913
- ${Xi(n)}${zi(o)}
2921
+ ${zs(n)}${Js(o)}
2914
2922
 
2915
2923
  ## Resources
2916
2924
 
2917
2925
  - [Documentation](/docs)
2918
2926
  - [GitHub](https://github.com/nebutra/nebutra-sailor)
2919
2927
  - [Get free license (Individual/OPC)](https://nebutra.com/get-license)
2920
- `}async function Ko(e,t){let{projectName:o,region:n,previewSelections:r=[],waveFeatures:s={}}=t;try{let i=gt.join(e,".sailor");Ue.existsSync(i)||Ue.mkdirSync(i,{recursive:!0}),Ue.writeFileSync(gt.join(i,"next-steps.md"),Ji(o,n,r,s))}catch(i){let c=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write .sailor/next-steps.md: ${c}`)}try{let i=gt.join(e,"apps","web");if(!Ue.existsSync(i))return;let c=gt.join(i,"src","app","[locale]","welcome");Ue.existsSync(c)||Ue.mkdirSync(c,{recursive:!0}),Ue.writeFileSync(gt.join(c,"page.tsx"),Hi(o))}catch(i){let c=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write welcome page: ${c}`)}}var Vo="create-sailor";function p(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2921
- `)}function ea(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function Bo(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 Yo(e){return e==="drizzle"?"drizzle":e==="none"?"none":"prisma"}function $o(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function qo(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 Go(e){if(!e)return"clerk";let t=e.toLowerCase();return t==="betterauth"||t==="better-auth"?"betterauth":t==="none"?"none":"clerk"}function Wo(e){if(!e)return["openai"];let t=e.split(",").map(o=>o.trim().toLowerCase());return t.includes("none")?[]:t}function ta(e,t){let o=e??t;return on(o)??o}var Ho={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function Xo(e,t){if(!e)return"fumadocs";let o=e.toLowerCase();if(o==="fumadocs"||o==="none")return o;if(o in Ho){let n=Ho[o];return t?p(!0,{event:"notice",kind:"docs-fallback",requested:o,effective:"fumadocs"}):process.stdout.write(N.yellow(`\u26A0 ${n} support is coming in v1.2. Falling back to fumadocs.
2922
- `)+N.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
2923
- `)),"fumadocs"}return"fumadocs"}function zo(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 Jo(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function na(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 Qo(e){return e==="cn"?"wechat":"stripe"}async function oa(){let e=new Qi;e.name(Vo).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(re,"-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>","expert: comma-separated provider ids used as an AI provider seed").option("--deploy <target>","vercel | railway | cloudflare | selfhost").option("--docs <id>","fumadocs | mintlify | docusaurus | nextra | vitepress | none").option("--email <id>","resend | postmark | ses | aliyun-dm | tencent-ses | netease | none").option("--storage <id>","r2 | s3 | supabase-storage | aliyun-oss | tencent-cos | qiniu | none").option("--monitoring <id>","sentry | datadog | aliyun-arms | tingyun | none").option("--analytics <id>","posthog | plausible | umami | baidu | sensors | none").option("--sms <id>","twilio | aliyun-sms | tencent-sms | yunpian | none").option("--queue <id>","qstash | bullmq | 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("--cron-jobs <bool>","true | false \u2014 scaffold scheduled cron handlers (default: true)").option("--audit-log <bool>","true | false \u2014 enable /settings/audit-log + arch test (default: true)").option("--api-keys <bool>","true | false \u2014 enable /settings/api-keys page (default: true)").option("--command-palette <bool>","true | false \u2014 enable \u2318K command palette (default: true)").option("--cookie-consent <bool>","true | false \u2014 enable GDPR/CCPA cookie banner (default: true)").option("--legal-pages <bool>","true | false \u2014 enable dynamic /legal/[slug] route (default: true)").option("--china-compliance <bool>","true | false \u2014 enable @nebutra/china-compliance + ICP footer (default: true when --region=cn, otherwise false)").option("--i18n","enable i18n").option("--no-i18n","disable i18n").option("--no-install","skip package install").option("--no-git","skip git init").option("-y, --yes","accept all defaults (non-interactive)").option("--dry-run","preview actions without writing files").option("--json","machine-readable output").option("--no-color","disable color output").option("-h, --help","show help"),e.parse(process.argv);let t=e.opts(),[o]=e.args;t.help&&(un(),process.exit(0));let n=!!t.json,r=!!t.dryRun,s=!!t.yes,i=s||!process.stdin.isTTY;n||pn(),p(n,{event:"start",version:re});let c=o??(s?"./my-saas-app":void 0),a;if(c)a=c;else if(i)a="./my-saas-app";else{let g=await R.group({name:()=>R.text({message:"Where should we create your project?",placeholder:"./my-saas-app",defaultValue:"./my-saas-app",validate:S=>{if(S.length===0)return"Please enter a path."}})},{onCancel:()=>{process.stdout.write(N.red(`\u2718 Cancelled
2924
- `)),process.exit(130)}});a=String(g.name)}let l=ft.basename(ft.resolve(a)),m=t.pm??ea(),y=!!t.region,k=!!t.auth,x=!!t.payment,L=!!t.ai,oe=!!t.email,b=!!t.storage,u=!!t.monitoring,T=!!t.analytics,yt=!!t.sms,sn=t.i18n!==void 0,h,Ze,J,et,K,M,q=Pn(t.socialLogin),tt,Lt,Se,Le,Q,V,St;if(i){h=Jo(t.region),Ze=Yo(t.orm),J=Bo(t.db);let g=x?t.payment:Qo(h);et=$o(g),K=qo(g),M=Go(t.auth);let S=Kt({mode:L?t.ai?.trim().toLowerCase()==="none"?"none":"direct":"gateway",providerIds:L?Wo(t.ai):void 0});tt=S.mode,Lt=S.routing,Se=S.providerIds,Q=zo(t.deploy),V=Xo(t.docs,n),St=sn?!!t.i18n:!0}else{let g={};y||(g.region=()=>R.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"})),k||(g.auth=()=>R.select({message:"Auth provider?",options:[{value:"clerk",label:"Clerk"},{value:"betterauth",label:"Better Auth"},{value:"none",label:"None"}],initialValue:"clerk"})),L||(g.aiMode=()=>R.select({message:"AI topology?",options:[{value:"gateway",label:"Multi-provider AI Gateway / router",hint:"recommended"},{value:"direct",label:"Direct SDK/provider adapters"},{value:"custom",label:"OpenAI-compatible endpoint"},{value:"none",label:"Skip AI"}],initialValue:"gateway"}),g.aiProviders=({results:_})=>{if(_.aiMode!=="direct")return Promise.resolve([]);let Z=Dt.map(jt=>({value:jt.id,label:`[${jt.category}] ${jt.name}`}));return R.multiselect({message:"Select direct AI provider adapters (expert path)",options:Z,initialValues:["openai"],required:!1})},g.customAiName=({results:_})=>_.aiMode==="custom"?R.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),g.customAiBaseUrl=({results:_})=>_.aiMode==="custom"?R.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:Z=>{if(Z.length===0)return"Base URL is required."}}):Promise.resolve(void 0),g.customAiApiKeyEnv=({results:_})=>_.aiMode==="custom"?R.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0));let S=Object.keys(g).length>0?await R.group(g,{onCancel:()=>{process.stdout.write(N.red(`\u2718 Cancelled
2925
- `)),process.exit(130)}}):{};h=Jo(y?t.region:S.region),Ze=Yo(t.orm),J=Bo(t.db);let B=x?t.payment:Qo(h);et=$o(B),K=qo(B),M=Go(k?t.auth:S.auth);let vt=S.aiMode==="custom"?{name:S.customAiName??"custom",baseURL:S.customAiBaseUrl??"",apiKeyEnvName:S.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,v=Kt({mode:L?t.ai?.trim().toLowerCase()==="none"?"none":"direct":S.aiMode??"gateway",providerIds:L?Wo(t.ai):S.aiProviders,customEndpoint:vt});tt=v.mode,Lt=v.routing,Se=v.providerIds,v.customEndpoint&&(Le={name:v.customEndpoint.name,baseURL:v.customEndpoint.baseURL,apiKeyEnvName:v.customEndpoint.apiKeyEnvName}),Q=zo(t.deploy),V=Xo(t.docs,n),St=sn?!!t.i18n:!0}let I=na(h),Me=oe?t.email:I.email,je=ta(b?t.storage:void 0,I.storage),Fe=u?t.monitoring:I.monitoring,De=T?t.analytics:I.analytics,Ke=yt?t.sms:I.sms,Ve=t.queue??I.queue,Be=t.search??I.search,nt=t.cache??I.cache,Ye=t.notifications??I.notifications,$e=t.webhooks??I.webhooks,ot=t.cms??I.cms,qe=t.featureFlags??I.featureFlags,Ge=t.captcha??I.captcha,ht=t.mcp??I.mcp,rt=t.metering??I.metering,We=t.billingMode??I.billingMode,He=t.idp??I.idp,C=jo({cronJobs:t.cronJobs,auditLog:t.auditLog,apiKeys:t.apiKeys,commandPalette:t.commandPalette,cookieConsent:t.cookieConsent,legalPages:t.legalPages,chinaCompliance:t.chinaCompliance},h),Xe=ln([{flag:"queue",provider:Ve},{flag:"search",provider:Be},{flag:"notifications",provider:Ye},{flag:"webhooks",provider:$e},{flag:"feature-flags",provider:qe},{flag:"captcha",provider:Ge}]);function Mt(){for(let g of Xe)if(n)p(!0,{event:"warn",step:g.flag,provider:g.provider,packageStatus:g.status,message:se(g.status)});else{let S=ze(g.status);process.stdout.write(N.yellow(`\u26A0 ${g.flag}=${g.provider} ${S} \u2014 ${se(g.status)}
2926
- `))}}let he={region:h,orm:Ze,database:J,payment:et,aiMode:tt,aiRouting:Lt,aiProviders:Se,customAiEndpoint:Le,deployTarget:Q,docs:V,i18n:St,email:Me,storage:je,monitoring:Fe,analytics:De,sms:Ke,queue:Ve,search:Be,cache:nt,notifications:Ye,webhooks:$e,cms:ot,featureFlags:qe,captcha:Ge,mcp:ht,metering:rt,billingMode:We,idp:He,cronJobs:C.cronJobs,auditLog:C.auditLog,apiKeys:C.apiKeys,commandPalette:C.commandPalette,cookieConsent:C.cookieConsent,legalPages:C.legalPages,chinaCompliance:C.chinaCompliance},Et=[["Project name",l],["Region",h],["Auth",M],["Social login",q.length>0?q.map(g=>st.find(S=>S.id===g)?.name??g).join(", "):"none"],["ORM",Ze],["Database",J],["Payment",K],["AI topology",`${tt}${Se.length>0?` (${Se.join(", ")} seed)`:""}${Le?" + custom endpoint":""}`],["Email",Me],["Storage",je],["Monitoring",Fe],["Analytics",De],["SMS",Ke],["Deploy Target",Q],["Docs Framework",V]];n?Et.forEach(([g,S],B)=>{p(!0,{event:"step",step:g,value:S,index:B+1,total:Et.length})}):Et.forEach(([g,S],B)=>{gn({index:B+1,total:Et.length,label:g,value:S})});let Zo={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""},an=Date.now();if(r){let g=Se.length,S=[`clone template \u2192 ${a}`,"write nebutra.config.json",`prune template (orm=${Ze}, i18n=${St})`,`region \u2192 ${h}`,`auth \u2192 ${M==="none"?"skip (remove packages/auth)":`configure ${M}`}`,...q.length>0?[`social-login \u2192 generate ${q.length} callback route${q.length===1?"":"s"} + SocialLoginButtons.tsx (${q.join(", ")})`]:[],`db \u2192 ${J==="none"?"skip (remove packages/db)":`configure Prisma for ${J}`}`,`payment \u2192 ${K==="none"?"skip (remove packages/billing)":`configure ${K}`}`,...V!=="none"?[`docs \u2192 scaffold apps/docs (${V==="fumadocs"?"fumadocs":`${V} \u2192 fumadocs fallback`})`]:[],...g>0||Le?[`ai-providers \u2192 generate ${tt} registry seed + env (${g}${Le?" + custom":""} provider${g===1&&!Le?"":"s"})`]:[],...Me!=="none"?[`email \u2192 configure ${Me}`]:[],...je!=="none"?[`storage \u2192 configure ${je}`]:[],...Fe!=="none"?[`monitoring \u2192 configure ${Fe}`]:[],...De!=="none"?[`analytics \u2192 configure ${De}`]:[],...Ke!=="none"?[`sms \u2192 configure ${Ke}`]:[],...Ve!=="none"?[`queue \u2192 configure ${Ve}`]:[],...Be!=="none"?[`search \u2192 configure ${Be}`]:[],...nt!=="none"?[`cache \u2192 configure ${nt}`]:[],...Ye!=="none"?[`notifications \u2192 configure ${Ye}`]:[],...$e!=="none"?[`webhooks \u2192 configure ${$e}`]:[],...ot!=="none"?[`cms \u2192 configure ${ot}`]:[],...qe!=="none"?[`feature-flags \u2192 configure ${qe}`]:[],...Ge!=="none"?[`captcha \u2192 configure ${Ge}`]:[],`mcp \u2192 ${ht==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${rt==="off"?"disabled":rt==="auto"?et!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...We!=="usage"?[`billing-mode \u2192 ${We}`]:[],...He!=="clerk"?[`idp \u2192 ${He}`]:[],`cron-jobs \u2192 ${C.cronJobs?"enabled":"disabled"}`,`audit-log \u2192 ${C.auditLog?"enabled":"disabled"}`,`api-keys \u2192 ${C.apiKeys?"enabled":"disabled"}`,`command-palette \u2192 ${C.commandPalette?"enabled":"disabled"}`,`cookie-consent \u2192 ${C.cookieConsent?"enabled":"disabled"}`,`legal-pages \u2192 ${C.legalPages?"enabled":"disabled"}`,`china-compliance \u2192 ${C.chinaCompliance?"enabled (@nebutra/china-compliance + ICP footer)":"disabled"}`,`compliance \u2192 inject ${h} boilerplate (ICP/Cookie/AIGC/Privacy)`,"welcome \u2192 generate dev welcome page","env \u2192 generate random secrets (AUTH_SECRET, JWT_SECRET)","seed \u2192 generate prisma/seed.ts (1 admin + 3 tenants)",...Q!=="none"?[`deploy \u2192 inject ${Q} config`]:[],"inject .env.local",t.install===!1?"skip install":`run ${m} install`,t.git===!1?"skip git init":"run git init"];if(n){for(let B of S)p(!0,{event:"plan",action:B});Mt(),p(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2927
- `+N.bold(`Dry run \u2014 planned actions:
2928
+ `}async function Vo(e,t){let{projectName:o,region:n,previewSelections:r=[],waveFeatures:i={}}=t;try{let s=ft.join(e,".sailor");Le.existsSync(s)||Le.mkdirSync(s,{recursive:!0}),Le.writeFileSync(ft.join(s,"next-steps.md"),Qs(o,n,r,i))}catch(s){let c=s instanceof Error?s.message:String(s);console.warn(`[create-sailor] Failed to write .sailor/next-steps.md: ${c}`)}try{let s=ft.join(e,"apps","web");if(!Le.existsSync(s))return;let c=ft.join(s,"src","app","[locale]","welcome");Le.existsSync(c)||Le.mkdirSync(c,{recursive:!0}),Le.writeFileSync(ft.join(c,"page.tsx"),Xs(o))}catch(s){let c=s instanceof Error?s.message:String(s);console.warn(`[create-sailor] Failed to write welcome page: ${c}`)}}var Bo="create-sailor";function p(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2929
+ `)}function ta(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function $o(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 Yo(e){return e==="drizzle"?"drizzle":e==="none"?"none":"prisma"}function qo(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function Go(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 Wo(e){if(!e)return"clerk";let t=e.toLowerCase();return t==="betterauth"||t==="better-auth"?"betterauth":t==="nextauth"||t==="next-auth"||t==="authjs"||t==="auth.js"?"nextauth":t==="none"?"none":"clerk"}function Ho(e){if(!e)return["openai"];let t=e.split(",").map(o=>o.trim().toLowerCase());return t.includes("none")?[]:t}function na(e,t){let o=e??t;return sn(o)??o}var Xo={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function zo(e,t){if(!e)return"fumadocs";let o=e.toLowerCase();if(o==="fumadocs"||o==="none")return o;if(o in Xo){let n=Xo[o];return t?p(!0,{event:"notice",kind:"docs-fallback",requested:o,effective:"fumadocs"}):process.stdout.write(C.yellow(`\u26A0 ${n} support is coming in v1.2. Falling back to fumadocs.
2930
+ `)+C.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
2931
+ `)),"fumadocs"}return"fumadocs"}function Jo(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 Qo(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function oa(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 Zo(e){return e==="cn"?"wechat":"stripe"}async function ra(){let e=new Zs;e.name(Bo).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(ie,"-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 | nextauth | none").option("--social-login <ids>","CN social login providers \u2014 wechat | qq | dingtalk | workweixin | feishu | weibo (comma-separated)").option("--payment <id>","stripe | lemon | wechat | alipay | none").option("--ai <ids>","expert: comma-separated provider ids used as an AI provider seed").option("--deploy <target>","vercel | railway | cloudflare | selfhost").option("--docs <id>","fumadocs | mintlify | docusaurus | nextra | vitepress | none").option("--email <id>","resend | postmark | ses | aliyun-dm | tencent-ses | netease | none").option("--storage <id>","r2 | s3 | supabase-storage | aliyun-oss | tencent-cos | qiniu | none").option("--monitoring <id>","sentry | datadog | aliyun-arms | tingyun | none").option("--analytics <id>","posthog | plausible | umami | baidu | sensors | none").option("--sms <id>","twilio | aliyun-sms | tencent-sms | yunpian | none").option("--queue <id>","qstash | bullmq | 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("--cron-jobs <bool>","true | false \u2014 scaffold scheduled cron handlers (default: true)").option("--audit-log <bool>","true | false \u2014 enable /settings/audit-log + arch test (default: true)").option("--api-keys <bool>","true | false \u2014 enable /settings/api-keys page (default: true)").option("--command-palette <bool>","true | false \u2014 enable \u2318K command palette (default: true)").option("--cookie-consent <bool>","true | false \u2014 enable GDPR/CCPA cookie banner (default: true)").option("--legal-pages <bool>","true | false \u2014 enable dynamic /legal/[slug] route (default: true)").option("--china-compliance <bool>","true | false \u2014 enable @nebutra/china-compliance + ICP footer (default: true when --region=cn, otherwise false)").option("--i18n","enable i18n").option("--no-i18n","disable i18n").option("--no-install","skip package install").option("--no-git","skip git init").option("-y, --yes","accept all defaults (non-interactive)").option("--dry-run","preview actions without writing files").option("--json","machine-readable output").option("--no-color","disable color output").option("-h, --help","show help"),e.parse(process.argv);let t=e.opts(),[o]=e.args;t.help&&(gn(),process.exit(0));let n=!!t.json,r=!!t.dryRun,i=!!t.yes,s=i||!process.stdin.isTTY;if(n||dn(),p(n,{event:"start",version:ie}),!t.pm)try{yt("pnpm --version",{stdio:"ignore"})}catch{n||process.stderr.write(`
2932
+ ${C.red("\u2718")} ${C.bold("pnpm is required")} but was not found on PATH.
2933
+
2934
+ The scaffold uses pnpm workspaces + Turborepo. Install pnpm first:
2935
+ ${C.cyan("npm i -g pnpm@10")}
2936
+
2937
+ Then retry: ${C.cyan("pnpm dlx create-sailor@latest")}
2938
+ (or pass ${C.dim("--pm=npm")} if you know workspace:* won't resolve in your setup)
2939
+
2940
+ `),p(n,{event:"error",code:"PNPM_MISSING"}),process.exit(1)}let c=o??(i?"./my-saas-app":void 0),a;if(c)a=c;else if(s)a="./my-saas-app";else{let g=await k.group({name:()=>k.text({message:"Where should we create your project?",placeholder:"./my-saas-app",defaultValue:"./my-saas-app",validate:S=>{if(S.length===0)return"Please enter a path."}})},{onCancel:()=>{process.stdout.write(C.red(`\u2718 Cancelled
2941
+ `)),process.exit(130)}});a=String(g.name)}let l=St.basename(St.resolve(a)),m=t.pm??ta(),y=!!t.region,x=!!t.auth,N=!!t.payment,L=!!t.ai,re=!!t.email,b=!!t.storage,u=!!t.monitoring,T=!!t.analytics,ht=!!t.sms,cn=t.i18n!==void 0,h,tt,Q,nt,K,M,G=Pn(t.socialLogin),ot,Mt,he,Me,Z,V,Et;if(s){h=Qo(t.region),tt=Yo(t.orm),Q=$o(t.db);let g=N?t.payment:Zo(h);nt=qo(g),K=Go(g),M=Wo(t.auth);let S=Vt({mode:L?t.ai?.trim().toLowerCase()==="none"?"none":"direct":"gateway",providerIds:L?Ho(t.ai):void 0});ot=S.mode,Mt=S.routing,he=S.providerIds,Z=Jo(t.deploy),V=zo(t.docs,n),Et=cn?!!t.i18n:!0}else{let g={};y||(g.region=()=>k.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"})),x||(g.auth=()=>k.select({message:"Auth provider?",options:[{value:"clerk",label:"Clerk",hint:"managed, fastest setup"},{value:"betterauth",label:"Better Auth",hint:"self-hosted, modern (2FA / passkeys / RBAC)"},{value:"nextauth",label:"NextAuth (Auth.js v5)",hint:"self-hosted, mature, large ecosystem"},{value:"none",label:"None"}],initialValue:"clerk"})),L||(g.aiMode=()=>k.select({message:"AI topology?",options:[{value:"gateway",label:"Multi-provider AI Gateway / router",hint:"recommended"},{value:"direct",label:"Direct SDK/provider adapters"},{value:"custom",label:"OpenAI-compatible endpoint"},{value:"none",label:"Skip AI"}],initialValue:"gateway"}),g.aiProviders=({results:_})=>{if(_.aiMode!=="direct")return Promise.resolve([]);let ee=Kt.map(Dt=>({value:Dt.id,label:`[${Dt.category}] ${Dt.name}`}));return k.multiselect({message:"Select direct AI provider adapters (expert path)",options:ee,initialValues:["openai"],required:!1})},g.customAiName=({results:_})=>_.aiMode==="custom"?k.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),g.customAiBaseUrl=({results:_})=>_.aiMode==="custom"?k.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:ee=>{if(ee.length===0)return"Base URL is required."}}):Promise.resolve(void 0),g.customAiApiKeyEnv=({results:_})=>_.aiMode==="custom"?k.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0));let S=Object.keys(g).length>0?await k.group(g,{onCancel:()=>{process.stdout.write(C.red(`\u2718 Cancelled
2942
+ `)),process.exit(130)}}):{};h=Qo(y?t.region:S.region),tt=Yo(t.orm),Q=$o(t.db);let B=N?t.payment:Zo(h);nt=qo(B),K=Go(B),M=Wo(x?t.auth:S.auth);let bt=S.aiMode==="custom"?{name:S.customAiName??"custom",baseURL:S.customAiBaseUrl??"",apiKeyEnvName:S.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,v=Vt({mode:L?t.ai?.trim().toLowerCase()==="none"?"none":"direct":S.aiMode??"gateway",providerIds:L?Ho(t.ai):S.aiProviders,customEndpoint:bt});ot=v.mode,Mt=v.routing,he=v.providerIds,v.customEndpoint&&(Me={name:v.customEndpoint.name,baseURL:v.customEndpoint.baseURL,apiKeyEnvName:v.customEndpoint.apiKeyEnvName}),Z=Jo(t.deploy),V=zo(t.docs,n),Et=cn?!!t.i18n:!0}let A=oa(h),Fe=re?t.email:A.email,De=na(b?t.storage:void 0,A.storage),je=u?t.monitoring:A.monitoring,Ke=T?t.analytics:A.analytics,Ve=ht?t.sms:A.sms,Be=t.queue??A.queue,$e=t.search??A.search,rt=t.cache??A.cache,Ye=t.notifications??A.notifications,qe=t.webhooks??A.webhooks,it=t.cms??A.cms,Ge=t.featureFlags??A.featureFlags,We=t.captcha??A.captcha,vt=t.mcp??A.mcp,st=t.metering??A.metering,He=t.billingMode??A.billingMode,Xe=t.idp??A.idp,I=Do({cronJobs:t.cronJobs,auditLog:t.auditLog,apiKeys:t.apiKeys,commandPalette:t.commandPalette,cookieConsent:t.cookieConsent,legalPages:t.legalPages,chinaCompliance:t.chinaCompliance},h),ze=un([{flag:"queue",provider:Be},{flag:"search",provider:$e},{flag:"notifications",provider:Ye},{flag:"webhooks",provider:qe},{flag:"feature-flags",provider:Ge},{flag:"captcha",provider:We}]);function Ft(){for(let g of ze)if(n)p(!0,{event:"warn",step:g.flag,provider:g.provider,packageStatus:g.status,message:se(g.status)});else{let S=Je(g.status);process.stdout.write(C.yellow(`\u26A0 ${g.flag}=${g.provider} ${S} \u2014 ${se(g.status)}
2943
+ `))}}let Ee={region:h,orm:tt,database:Q,payment:nt,aiMode:ot,aiRouting:Mt,aiProviders:he,customAiEndpoint:Me,deployTarget:Z,docs:V,i18n:Et,email:Fe,storage:De,monitoring:je,analytics:Ke,sms:Ve,queue:Be,search:$e,cache:rt,notifications:Ye,webhooks:qe,cms:it,featureFlags:Ge,captcha:We,mcp:vt,metering:st,billingMode:He,idp:Xe,cronJobs:I.cronJobs,auditLog:I.auditLog,apiKeys:I.apiKeys,commandPalette:I.commandPalette,cookieConsent:I.cookieConsent,legalPages:I.legalPages,chinaCompliance:I.chinaCompliance},_t=[["Project name",l],["Region",h],["Auth",M],["Social login",G.length>0?G.map(g=>at.find(S=>S.id===g)?.name??g).join(", "):"none"],["ORM",tt],["Database",Q],["Payment",K],["AI topology",`${ot}${he.length>0?` (${he.join(", ")} seed)`:""}${Me?" + custom endpoint":""}`],["Email",Fe],["Storage",De],["Monitoring",je],["Analytics",Ke],["SMS",Ve],["Deploy Target",Z],["Docs Framework",V]];n?_t.forEach(([g,S],B)=>{p(!0,{event:"step",step:g,value:S,index:B+1,total:_t.length})}):_t.forEach(([g,S],B)=>{yn({index:B+1,total:_t.length,label:g,value:S})});let er={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""},pn=Date.now();if(r){let g=he.length,S=[`clone template \u2192 ${a}`,"write nebutra.config.json",`prune template (orm=${tt}, i18n=${Et})`,`region \u2192 ${h}`,`auth \u2192 ${M==="none"?"skip (remove packages/auth)":`configure ${M}`}`,...G.length>0?[`social-login \u2192 generate ${G.length} callback route${G.length===1?"":"s"} + SocialLoginButtons.tsx (${G.join(", ")})`]:[],`db \u2192 ${Q==="none"?"skip (remove packages/db)":`configure Prisma for ${Q}`}`,`payment \u2192 ${K==="none"?"skip (remove packages/billing)":`configure ${K}`}`,...V!=="none"?[`docs \u2192 scaffold apps/docs (${V==="fumadocs"?"fumadocs":`${V} \u2192 fumadocs fallback`})`]:[],...g>0||Me?[`ai-providers \u2192 generate ${ot} registry seed + env (${g}${Me?" + custom":""} provider${g===1&&!Me?"":"s"})`]:[],...Fe!=="none"?[`email \u2192 configure ${Fe}`]:[],...De!=="none"?[`storage \u2192 configure ${De}`]:[],...je!=="none"?[`monitoring \u2192 configure ${je}`]:[],...Ke!=="none"?[`analytics \u2192 configure ${Ke}`]:[],...Ve!=="none"?[`sms \u2192 configure ${Ve}`]:[],...Be!=="none"?[`queue \u2192 configure ${Be}`]:[],...$e!=="none"?[`search \u2192 configure ${$e}`]:[],...rt!=="none"?[`cache \u2192 configure ${rt}`]:[],...Ye!=="none"?[`notifications \u2192 configure ${Ye}`]:[],...qe!=="none"?[`webhooks \u2192 configure ${qe}`]:[],...it!=="none"?[`cms \u2192 configure ${it}`]:[],...Ge!=="none"?[`feature-flags \u2192 configure ${Ge}`]:[],...We!=="none"?[`captcha \u2192 configure ${We}`]:[],`mcp \u2192 ${vt==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${st==="off"?"disabled":st==="auto"?nt!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...He!=="usage"?[`billing-mode \u2192 ${He}`]:[],...Xe!=="clerk"?[`idp \u2192 ${Xe}`]:[],`cron-jobs \u2192 ${I.cronJobs?"enabled":"disabled"}`,`audit-log \u2192 ${I.auditLog?"enabled":"disabled"}`,`api-keys \u2192 ${I.apiKeys?"enabled":"disabled"}`,`command-palette \u2192 ${I.commandPalette?"enabled":"disabled"}`,`cookie-consent \u2192 ${I.cookieConsent?"enabled":"disabled"}`,`legal-pages \u2192 ${I.legalPages?"enabled":"disabled"}`,`china-compliance \u2192 ${I.chinaCompliance?"enabled (@nebutra/china-compliance + ICP footer)":"disabled"}`,`compliance \u2192 inject ${h} boilerplate (ICP/Cookie/AIGC/Privacy)`,"welcome \u2192 generate dev welcome page","env \u2192 generate random secrets (AUTH_SECRET, JWT_SECRET)","seed \u2192 generate prisma/seed.ts (1 admin + 3 tenants)",...Z!=="none"?[`deploy \u2192 inject ${Z} config`]:[],"inject .env.local",t.install===!1?"skip install":`run ${m} install`,t.git===!1?"skip git init":"run git init"];if(n){for(let B of S)p(!0,{event:"plan",action:B});Ft(),p(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2944
+ `+C.bold(`Dry run \u2014 planned actions:
2928
2945
  `));for(let B of S)process.stdout.write(` \u2022 ${B}
2929
- `);Xe.length>0&&(process.stdout.write(`
2930
- `+N.bold(N.yellow(`Preview-status providers selected:
2931
- `))),Mt()),process.stdout.write(N.dim(`
2946
+ `);ze.length>0&&(process.stdout.write(`
2947
+ `+C.bold(C.yellow(`Preview-status providers selected:
2948
+ `))),Ft()),process.stdout.write(C.dim(`
2932
2949
  No files were written.
2933
- `))}process.exit(0)}let er=async()=>{process.stdout.write(`
2934
- `+N.red(`\u2718 Cancelled
2935
- `)),ye.existsSync(a)&&await R.confirm({message:`Cleanup partial install at ${a}?`,initialValue:!0})===!0&&(ye.rmSync(a,{recursive:!0,force:!0}),process.stdout.write(N.dim(` \u2713 Removed ${a}
2936
- `))),process.exit(130)};process.on("SIGINT",er);try{p(n,{event:"step",step:"clone",status:"start"}),await so(a),p(n,{event:"step",step:"clone",status:"ok"}),p(n,{event:"step",step:"package",status:"start"}),await fo(a,l),p(n,{event:"step",step:"package",status:"ok"}),p(n,{event:"step",step:"config",status:"start"}),await Un(a,he),p(n,{event:"step",step:"config",status:"ok"}),p(n,{event:"step",step:"prune",status:"start"}),await Co(a,he),p(n,{event:"step",step:"prune",status:"ok"});let g=ft.join(a,"packages/db/prisma/schema.prisma");if(ye.existsSync(g)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let v=ye.readFileSync(g,"utf-8"),_=Zt(v,{auth:M,payment:K,"billing-mode":We,idp:He,template:"saas"});ye.writeFileSync(g,_),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(v){let _=v instanceof Error?v.message:String(v);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:M,status:"start"}),await _n(a,M),p(n,{event:"step",step:"auth",choice:M,status:"ok"}),q.length>0?(p(n,{event:"step",step:"social-login",providers:q,status:"start"}),await In(a,q,M),p(n,{event:"step",step:"social-login",providers:q,status:"ok"})):p(n,{event:"step",step:"social-login",status:"skip"}),p(n,{event:"step",step:"db",choice:J,status:"start"}),await jn(a,J,l),p(n,{event:"step",step:"db",choice:J,status:"ok"}),p(n,{event:"step",step:"payment",choice:K,status:"start"}),await So(a,K),p(n,{event:"step",step:"payment",choice:K,status:"ok"}),await qn(a,Me,h),n&&p(!0,{event:"step",step:"email",choice:Me,status:"ok"}),await Mo(a,je,h),n&&p(!0,{event:"step",step:"storage",choice:je,status:"ok"}),await uo(a,Fe,h),n&&p(!0,{event:"step",step:"monitoring",choice:Fe,status:"ok"}),await Sn(a,De,h),n&&p(!0,{event:"step",step:"analytics",choice:De,status:"ok"}),await Uo(a,Ke,h),n&&p(!0,{event:"step",step:"sms",choice:Ke,status:"ok"}),await Ro(a,Ve,h),n&&p(!0,{event:"step",step:"queue",choice:Ve,status:"ok"}),await No(a,Be,h),n&&p(!0,{event:"step",step:"search",choice:Be,status:"ok"}),await Rn(a,nt,h),n&&p(!0,{event:"step",step:"cache",choice:nt,status:"ok"}),await go(a,Ye,h),n&&p(!0,{event:"step",step:"notifications",choice:Ye,status:"ok"}),await Do(a,$e,h),n&&p(!0,{event:"step",step:"webhooks",choice:$e,status:"ok"}),await Tn(a,ot,h),n&&p(!0,{event:"step",step:"cms",choice:ot,status:"ok"}),await Qn(a,qe,h),n&&p(!0,{event:"step",step:"feature-flags",choice:qe,status:"ok"}),await xn(a,Ge,h),n&&p(!0,{event:"step",step:"captcha",choice:Ge,status:"ok"}),await io(a,ht),n&&p(!0,{event:"step",step:"mcp",mode:ht,status:"ok"}),await co(a,rt,et),n&&p(!0,{event:"step",step:"metering",mode:rt,status:"ok"}),p(n,{event:"step",step:"prune-wave-features",status:"start"}),Io(a,C),p(n,{event:"step",step:"prune-wave-features",status:"ok",toggles:C}),he.orm==="prisma"&&he.database!=="none"){let v=ft.join(a,"packages/db/prisma/schema.prisma");if(ye.existsSync(v)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let _=ye.readFileSync(v,"utf8"),Z=Zt(_,{auth:M,payment:K,"billing-mode":We,idp:He,template:"saas"});ye.writeFileSync(v,Z),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(_){let Z=_ instanceof Error?_.message:String(_);p(n,{event:"step",step:"schema-prune",status:"error",error:Z})}}else p(n,{event:"step",step:"schema-prune",status:"skip"})}else p(n,{event:"step",step:"schema-prune",status:"skip"});if(p(n,{event:"step",step:"billing-mode",choice:We,status:"ok"}),p(n,{event:"step",step:"idp",choice:He,status:"ok"}),await On(a,h),n&&p(!0,{event:"step",step:"compliance",region:h,status:"ok"}),await zn(a),await To(a,M),await Ko(a,{projectName:l,region:h,previewSelections:Xe,waveFeatures:C}),he.aiMode!=="none"){p(n,{event:"step",step:"ai-providers",status:"start"});let v={providerIds:he.aiProviders,customEndpoint:he.customAiEndpoint},_=ft.join(a,"packages/ai-providers/templates");await bo(a,v,_),p(n,{event:"step",step:"ai-providers",status:"ok"})}else p(n,{event:"step",step:"ai-providers",status:"skip"});if(p(n,{event:"step",step:"docs",status:"start"}),V!=="none"?(await Vn(a,{framework:V,projectName:l}),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 Fn(a,Q),p(n,{event:"step",step:"deploy-target",status:"ok"}),p(n,{event:"step",step:"env",status:"start"}),await Wn(a,Zo),p(n,{event:"step",step:"env",status:"ok"}),t.install!==!1){let v=m==="bun"?"bun install":`${m} install`;n?p(!0,{event:"step",step:"install",pm:m,status:"start"}):process.stdout.write(N.dim(` Installing dependencies with ${m}\u2026
2937
- `));try{Ut(v,{cwd:a,stdio:n?"ignore":"inherit"}),p(n,{event:"step",step:"install",status:"ok"})}catch(_){let Z=_ instanceof Error?_.message:String(_);n?p(!0,{event:"step",step:"install",status:"error",error:Z}):process.stdout.write(N.yellow(` \u26A0 install failed \u2014 run '${v}' manually.
2938
- `))}}else p(n,{event:"step",step:"install",status:"skip"});if(t.git!==!1){n&&p(!0,{event:"step",step:"git-init",status:"start"});try{Ut("git init -q",{cwd:a,stdio:"ignore"}),Ut("git add -A",{cwd:a,stdio:"ignore"}),Ut('git -c user.email=you@example.com -c user.name="You" commit -q -m "chore: initial scaffold from create-sailor"',{cwd:a,stdio:"ignore"}),p(n,{event:"step",step:"git-init",status:"ok"})}catch(v){let _=v instanceof Error?v.message:String(v);n?p(!0,{event:"step",step:"git-init",status:"error",error:_}):process.stdout.write(N.yellow(` \u26A0 git init skipped \u2014 not fatal.
2939
- `))}}else p(n,{event:"step",step:"git-init",status:"skip"});let vt=Math.max(1,Math.round((Date.now()-an)/1e3));hn({template_version:re,package_manager:m,region:h,auth:M,payment:K,ai_providers:Se,deploy_target:Q,duration_ms:Date.now()-an}),Xe.length>0&&Mt(),n?p(!0,{event:"done",status:"ok",elapsedSec:vt,targetDir:a,previewSelections:Xe,waveFeatures:C}):dn({elapsedSec:vt,targetDir:a,skippedInstall:t.install===!1,previewSelections:Xe,waveFeatures:C});try{Zi({pkg:{name:Vo,version:re},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}process.exit(0)}catch(g){let S=g instanceof Error?g.message:String(g);n?p(!0,{event:"error",message:S}):process.stdout.write(N.red(`
2950
+ `))}process.exit(0)}let tr=async()=>{process.stdout.write(`
2951
+ `+C.red(`\u2718 Cancelled
2952
+ `)),Se.existsSync(a)&&await k.confirm({message:`Cleanup partial install at ${a}?`,initialValue:!0})===!0&&(Se.rmSync(a,{recursive:!0,force:!0}),process.stdout.write(C.dim(` \u2713 Removed ${a}
2953
+ `))),process.exit(130)};process.on("SIGINT",tr);try{p(n,{event:"step",step:"clone",status:"start"}),await so(a),p(n,{event:"step",step:"clone",status:"ok"}),p(n,{event:"step",step:"package",status:"start"}),await yo(a,l),p(n,{event:"step",step:"package",status:"ok"}),p(n,{event:"step",step:"config",status:"start"}),await Un(a,Ee),p(n,{event:"step",step:"config",status:"ok"}),p(n,{event:"step",step:"prune",status:"start"}),await Io(a,Ee),p(n,{event:"step",step:"prune",status:"ok"});let g=St.join(a,"packages/platform/db/prisma/schema.prisma");if(Se.existsSync(g)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let v=Se.readFileSync(g,"utf-8"),_=tn(v,{auth:M,payment:K,"billing-mode":He,idp:Xe,template:"saas"});Se.writeFileSync(g,_),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(v){let _=v instanceof Error?v.message:String(v);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:M,status:"start"}),await _n(a,M),p(n,{event:"step",step:"auth",choice:M,status:"ok"}),G.length>0?(p(n,{event:"step",step:"social-login",providers:G,status:"start"}),await In(a,G,M),p(n,{event:"step",step:"social-login",providers:G,status:"ok"})):p(n,{event:"step",step:"social-login",status:"skip"}),p(n,{event:"step",step:"db",choice:Q,status:"start"}),await Fn(a,Q,l),p(n,{event:"step",step:"db",choice:Q,status:"ok"}),p(n,{event:"step",step:"payment",choice:K,status:"start"}),await ho(a,K),p(n,{event:"step",step:"payment",choice:K,status:"ok"}),await Gn(a,Fe,h),n&&p(!0,{event:"step",step:"email",choice:Fe,status:"ok"}),await Fo(a,De,h),n&&p(!0,{event:"step",step:"storage",choice:De,status:"ok"}),await mo(a,je,h),n&&p(!0,{event:"step",step:"monitoring",choice:je,status:"ok"}),await En(a,Ke,h),n&&p(!0,{event:"step",step:"analytics",choice:Ke,status:"ok"}),await Lo(a,Ve,h),n&&p(!0,{event:"step",step:"sms",choice:Ve,status:"ok"}),await ko(a,Be,h),n&&p(!0,{event:"step",step:"queue",choice:Be,status:"ok"}),await To(a,$e,h),n&&p(!0,{event:"step",step:"search",choice:$e,status:"ok"}),await Rn(a,rt,h),n&&p(!0,{event:"step",step:"cache",choice:rt,status:"ok"}),await fo(a,Ye,h),n&&p(!0,{event:"step",step:"notifications",choice:Ye,status:"ok"}),await Ko(a,qe,h),n&&p(!0,{event:"step",step:"webhooks",choice:qe,status:"ok"}),await Tn(a,it,h),n&&p(!0,{event:"step",step:"cms",choice:it,status:"ok"}),await Zn(a,Ge,h),n&&p(!0,{event:"step",step:"feature-flags",choice:Ge,status:"ok"}),await xn(a,We,h),n&&p(!0,{event:"step",step:"captcha",choice:We,status:"ok"}),await ao(a,vt),n&&p(!0,{event:"step",step:"mcp",mode:vt,status:"ok"}),await po(a,st,nt),n&&p(!0,{event:"step",step:"metering",mode:st,status:"ok"}),p(n,{event:"step",step:"prune-wave-features",status:"start"}),Ao(a,I),p(n,{event:"step",step:"prune-wave-features",status:"ok",toggles:I}),Ee.orm==="prisma"&&Ee.database!=="none"){let v=St.join(a,"packages/platform/db/prisma/schema.prisma");if(Se.existsSync(v)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let _=Se.readFileSync(v,"utf8"),ee=tn(_,{auth:M,payment:K,"billing-mode":He,idp:Xe,template:"saas"});Se.writeFileSync(v,ee),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(_){let ee=_ instanceof Error?_.message:String(_);p(n,{event:"step",step:"schema-prune",status:"error",error:ee})}}else p(n,{event:"step",step:"schema-prune",status:"skip"})}else p(n,{event:"step",step:"schema-prune",status:"skip"});if(p(n,{event:"step",step:"billing-mode",choice:He,status:"ok"}),p(n,{event:"step",step:"idp",choice:Xe,status:"ok"}),await On(a,h),n&&p(!0,{event:"step",step:"compliance",region:h,status:"ok"}),await Jn(a),await Oo(a,M),await Vo(a,{projectName:l,region:h,previewSelections:ze,waveFeatures:I}),Ee.aiMode!=="none"){p(n,{event:"step",step:"ai-providers",status:"start"});let v={providerIds:Ee.aiProviders,customEndpoint:Ee.customAiEndpoint},_=St.join(a,"packages/ai/ai-providers/templates");await Po(a,v,_),p(n,{event:"step",step:"ai-providers",status:"ok"})}else p(n,{event:"step",step:"ai-providers",status:"skip"});if(p(n,{event:"step",step:"docs",status:"start"}),V!=="none"?(await Bn(a,{framework:V,projectName:l}),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"}),Z!=="none"&&await jn(a,Z),p(n,{event:"step",step:"deploy-target",status:"ok"}),p(n,{event:"step",step:"env",status:"start"}),await Hn(a,er),p(n,{event:"step",step:"env",status:"ok"}),t.install!==!1){let v=m==="bun"?"bun install":`${m} install`;n?p(!0,{event:"step",step:"install",pm:m,status:"start"}):process.stdout.write(C.dim(` Installing dependencies with ${m}\u2026
2954
+ `));try{yt(v,{cwd:a,stdio:n?"ignore":"inherit"}),p(n,{event:"step",step:"install",status:"ok"})}catch(_){let ee=_ instanceof Error?_.message:String(_);n?p(!0,{event:"step",step:"install",status:"error",error:ee}):process.stdout.write(C.yellow(` \u26A0 install failed \u2014 run '${v}' manually.
2955
+ `))}}else p(n,{event:"step",step:"install",status:"skip"});if(t.git!==!1){n&&p(!0,{event:"step",step:"git-init",status:"start"});try{yt("git init -q",{cwd:a,stdio:"ignore"}),yt("git add -A",{cwd:a,stdio:"ignore"}),yt('git -c user.email=you@example.com -c user.name="You" commit -q -m "chore: initial scaffold from create-sailor"',{cwd:a,stdio:"ignore"}),p(n,{event:"step",step:"git-init",status:"ok"})}catch(v){let _=v instanceof Error?v.message:String(v);n?p(!0,{event:"step",step:"git-init",status:"error",error:_}):process.stdout.write(C.yellow(` \u26A0 git init skipped \u2014 not fatal.
2956
+ `))}}else p(n,{event:"step",step:"git-init",status:"skip"});let bt=Math.max(1,Math.round((Date.now()-pn)/1e3));vn({template_version:ie,package_manager:m,region:h,auth:M,payment:K,ai_providers:he,deploy_target:Z,duration_ms:Date.now()-pn}),ze.length>0&&Ft(),n?p(!0,{event:"done",status:"ok",elapsedSec:bt,targetDir:a,previewSelections:ze,waveFeatures:I}):mn({elapsedSec:bt,targetDir:a,skippedInstall:t.install===!1,previewSelections:ze,waveFeatures:I});try{ea({pkg:{name:Bo,version:ie},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}process.exit(0)}catch(g){let S=g instanceof Error?g.message:String(g);n?p(!0,{event:"error",message:S}):process.stdout.write(C.red(`
2940
2957
  \u2718 Failed: ${S}
2941
- `)),process.exit(1)}}oa().catch(e=>{process.stderr.write(String(e)+`
2958
+ `)),process.exit(1)}}ra().catch(e=>{process.stderr.write(String(e)+`
2942
2959
  `),process.exit(1)});