create-sailor 1.3.6 → 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 (99) hide show
  1. package/README.md +19 -0
  2. package/dist/index.js +232 -208
  3. package/package.json +14 -14
  4. package/templates/deploy/Dockerfile.web +57 -0
  5. package/templates/deploy/docker-compose.yml +40 -0
  6. package/templates/deploy/railway.toml +13 -0
  7. package/templates/deploy/vercel.json +37 -0
  8. package/templates/deploy/wrangler.toml +8 -0
  9. package/templates/docs/docusaurus/README.md +24 -0
  10. package/templates/docs/docusaurus/docs/getting-started/develop.md +20 -0
  11. package/templates/docs/docusaurus/docs/getting-started/install.md +11 -0
  12. package/templates/docs/docusaurus/docs/intro.md +15 -0
  13. package/templates/docs/docusaurus/docusaurus.config.ts +66 -0
  14. package/templates/docs/docusaurus/package.json +43 -0
  15. package/templates/docs/docusaurus/sidebars.ts +14 -0
  16. package/templates/docs/docusaurus/src/css/custom.css +22 -0
  17. package/templates/docs/docusaurus/tsconfig.json +7 -0
  18. package/templates/docs/fumadocs/README.md +46 -0
  19. package/templates/docs/fumadocs/app/(home)/page.tsx +22 -0
  20. package/templates/docs/fumadocs/app/api/search/route.ts +4 -0
  21. package/templates/docs/fumadocs/app/docs/[[...slug]]/page.tsx +39 -0
  22. package/templates/docs/fumadocs/app/docs/layout.tsx +11 -0
  23. package/templates/docs/fumadocs/app/global.css +10 -0
  24. package/templates/docs/fumadocs/app/layout.tsx +18 -0
  25. package/templates/docs/fumadocs/content/docs/api.mdx +31 -0
  26. package/templates/docs/fumadocs/content/docs/concepts.mdx +19 -0
  27. package/templates/docs/fumadocs/content/docs/getting-started.mdx +56 -0
  28. package/templates/docs/fumadocs/content/docs/index.mdx +17 -0
  29. package/templates/docs/fumadocs/content/docs/meta.json +4 -0
  30. package/templates/docs/fumadocs/lib/source.ts +7 -0
  31. package/templates/docs/fumadocs/next.config.mjs +17 -0
  32. package/templates/docs/fumadocs/package.json +30 -0
  33. package/templates/docs/fumadocs/source.config.ts +17 -0
  34. package/templates/docs/fumadocs/tsconfig.json +25 -0
  35. package/templates/docs/mintlify/README.md +25 -0
  36. package/templates/docs/mintlify/api-reference/introduction.mdx +25 -0
  37. package/templates/docs/mintlify/introduction.mdx +21 -0
  38. package/templates/docs/mintlify/mint.json +37 -0
  39. package/templates/docs/mintlify/package.json +13 -0
  40. package/templates/docs/mintlify/quickstart.mdx +26 -0
  41. package/templates/docs/nextra/README.md +35 -0
  42. package/templates/docs/nextra/app/[[...mdxPath]]/page.tsx +23 -0
  43. package/templates/docs/nextra/app/layout.tsx +36 -0
  44. package/templates/docs/nextra/content/_meta.ts +4 -0
  45. package/templates/docs/nextra/content/getting-started.mdx +35 -0
  46. package/templates/docs/nextra/content/index.mdx +18 -0
  47. package/templates/docs/nextra/mdx-components.tsx +10 -0
  48. package/templates/docs/nextra/next.config.mjs +9 -0
  49. package/templates/docs/nextra/package.json +24 -0
  50. package/templates/docs/nextra/tsconfig.json +21 -0
  51. package/templates/docs/vitepress/.vitepress/config.ts +35 -0
  52. package/templates/docs/vitepress/README.md +23 -0
  53. package/templates/docs/vitepress/guide/getting-started.md +26 -0
  54. package/templates/docs/vitepress/guide/introduction.md +12 -0
  55. package/templates/docs/vitepress/index.md +23 -0
  56. package/templates/docs/vitepress/package.json +17 -0
  57. package/templates/docs/vitepress/tsconfig.json +15 -0
  58. package/dist/aws-kms-ZX6CTY62.js +0 -1
  59. package/dist/chunk-4NVBWJ2Q.js +0 -1
  60. package/dist/chunk-7DCGNQSQ.js +0 -5
  61. package/dist/chunk-7HOF72FC.js +0 -1
  62. package/dist/chunk-7VJYOZUP.js +0 -2
  63. package/dist/chunk-A2KGYHAM.js +0 -1
  64. package/dist/chunk-A75AMTOI.js +0 -1
  65. package/dist/chunk-B5RLHF2U.js +0 -40
  66. package/dist/chunk-DIXI4M5O.js +0 -1
  67. package/dist/chunk-EXLRPVEX.js +0 -1
  68. package/dist/chunk-FGJ5K4WM.js +0 -1
  69. package/dist/chunk-FSRPMVAS.js +0 -1
  70. package/dist/chunk-J7NVVT5I.js +0 -20
  71. package/dist/chunk-LDOHSEAR.js +0 -9
  72. package/dist/chunk-NK255JZN.js +0 -1
  73. package/dist/chunk-OJM5Y4UT.js +0 -1
  74. package/dist/chunk-PXU2OOBT.js +0 -1
  75. package/dist/chunk-QEIMNOY2.js +0 -1
  76. package/dist/chunk-QMKVUKS6.js +0 -1
  77. package/dist/chunk-RR5R4AKJ.js +0 -1
  78. package/dist/chunk-SDX64WW4.js +0 -23
  79. package/dist/chunk-XSSPJU77.js +0 -1
  80. package/dist/chunk-YR32FZAX.js +0 -1
  81. package/dist/credits-6AUSU6X6.js +0 -1787
  82. package/dist/dist-B4YTE2SQ.js +0 -5
  83. package/dist/dist-es-4EORLV5B.js +0 -1
  84. package/dist/dist-es-7IMKW7US.js +0 -1
  85. package/dist/dist-es-FJUQ4DBK.js +0 -2
  86. package/dist/dist-es-GP7DK3S3.js +0 -5
  87. package/dist/dist-es-JXNWCJHW.js +0 -1
  88. package/dist/dist-es-YKXA2GQ2.js +0 -1
  89. package/dist/dist-es-ZA2NRM7G.js +0 -2
  90. package/dist/event-streams-T5RU6C4N.js +0 -1
  91. package/dist/index.d.ts +0 -1
  92. package/dist/loadSso-YQ73JVR6.js +0 -1
  93. package/dist/local-WW37QOXE.js +0 -1
  94. package/dist/query_compiler_fast_bg.postgresql-PN2AWLCP.js +0 -2
  95. package/dist/query_compiler_fast_bg.postgresql.wasm-base64-CASS54LO.js +0 -1
  96. package/dist/signin-LD4OP44K.js +0 -1
  97. package/dist/src-MVDQLN5F.js +0 -1
  98. package/dist/sso-oidc-4BAF7BYK.js +0 -1
  99. package/dist/sts-3V5Q4UTA.js +0 -6
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import"./chunk-FSRPMVAS.js";import{execSync as kt}from"child_process";import de from"fs";import ut from"path";import*as C from"@clack/prompts";import{Command as Bs}from"commander";import w from"picocolors";import Ys from"update-notifier";import Xo from"cfonts";import zo from"picocolors";import nn from"fs";import Lt from"path";import{fileURLToPath as Ho}from"url";function Wo(){try{let t=Lt.dirname(Ho(import.meta.url));for(let o=0;o<4;o++){let n=Lt.join(t,"package.json");if(nn.existsSync(n)){let r=nn.readFileSync(n,"utf-8"),i=JSON.parse(r);if(i.name==="create-sailor"&&typeof i.version=="string")return i.version}t=Lt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var ee=Wo();function on(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${ee}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
3
- `));return}Xo.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(zo.dim(` AI-Native SaaS Template \xB7 v${ee} \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 _ from"picocolors";var Qo={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 Jo(e){return e?Qo[e]??"stable":"stable"}function qe(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function te(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 rn(e){let t=[];for(let{flag:o,provider:n}of e){if(!n||n==="none")continue;let r=Jo(n);r!=="stable"&&t.push({flag:o,provider:n,status:r})}return t}function Zo(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function sn(e){let t=Zo(),o=t?"\u2693":"-",n=t?"\u25B8":"->",r=t?"\u2605":"*",i=t?"\u{1F4E7}":"*",c=["",` ${t?_.bold(`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`):`${o} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`}`,"",` ${t?_.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?_.dim("\u2192 add provider keys before booting apps"):"-> add provider keys before booting apps"}`,` ${n} pnpm db:migrate ${t?_.dim("\u2192 sync Prisma schema"):"-> sync Prisma schema"}`,` ${n} pnpm db:seed ${t?_.dim("\u2192 load example tenants and records"):"-> load example tenants and records"}`,` ${n} pnpm dev ${t?_.dim("\u2192 http://localhost:3000"):"-> http://localhost:3000"}`,"",` ${t?_.bold("Customize:"):"Customize:"}`,` ${n} pnpm brand:init ${t?_.dim("\u2192 create brand.config.ts"):"-> create brand.config.ts"}`,` ${n} pnpm brand:apply ${t?_.dim("\u2192 propagate brand changes"):"-> propagate brand changes"}`,` ${n} pnpm preset:env ${t?_.dim("\u2192 review preset env requirements"):"-> review preset env requirements"}`,"",` ${t?_.bold("Useful scripts:"):"Useful scripts:"}`,` ${n} pnpm infra:up ${t?_.dim("\u2192 start local PostgreSQL/Redis/ClickHouse"):"-> start local PostgreSQL/Redis/ClickHouse"}`,` ${n} pnpm generate:api-types ${t?_.dim("\u2192 refresh shared API client types"):"-> refresh shared API client types"}`,` ${n} pnpm lint ${t?_.dim("\u2192 quick repo sanity check"):"-> quick repo sanity check"}`);let a=e.previewSelections??[];if(a.length>0){let d=t?_.bold(_.yellow("\u26A0 Preview features selected:")):"!! Preview features selected:";c.push("",` ${d}`);for(let u of a){let h=qe(u.status),O=` ${n} ${u.flag} (${u.provider}) ${h}`;c.push(t?_.yellow(O):O)}c.push("",` ${t?_.dim(te("foundation")):te("foundation")}`,` ${t?_.dim("You may need to contribute the provider integration yourself."):"You may need to contribute the provider integration yourself."}`,` ${t?_.dim("See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"):"See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"}`)}c.push("",` ${t?_.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(`
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 er=`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 an(){process.stdout.write(er)}import Et from"picocolors";function cn(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function tr(e){let t=cn()?"\u25B8":"->",o=`[${e.index}/${e.total}]`,n=e.label.padEnd(18," ");return cn()?`${Et.dim(o)} ${Et.bold(n)} ${Et.dim(t)} ${Et.cyan(e.value)}`:`${o} ${n} ${t} ${e.value}`}function pn(e){process.stdout.write(tr(e)+`
77
- `)}var Mt=[{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:[]}],pa=Mt.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var nr=["openai","anthropic","google"],or=["openai"];function Dt(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let o=t.length>0?t:[...nr];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:[...or];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 Ge from"fs";import k from"path";var ln=[{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:""}],ua=ln.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function dn(e){return ln.find(t=>t.id===e)}function rr(e){Ge.mkdirSync(e,{recursive:!0})}function $(e,t){rr(k.dirname(e)),Ge.writeFileSync(e,t)}function ge(e,t){let o=k.join(e,".env.example");Ge.existsSync(o)?Ge.appendFileSync(o,`
78
- `+t):Ge.writeFileSync(o,t)}function ir(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
- `;$(k.join(e,"src","lib","analytics","posthog.client.ts"),t),$(k.join(e,"src","lib","analytics","posthog.server.ts"),o),$(k.join(e,"src","components","analytics","AnalyticsProvider.tsx"),n)}function sr(){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 ar(e){$(k.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 cr(){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 pr(e){$(k.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 lr(){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 dr(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
- `;$(k.join(e,"src","lib","analytics","mixpanel.client.ts"),t),$(k.join(e,"src","lib","analytics","mixpanel.server.ts"),o)}function ur(){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 mr(e){$(k.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 gr(){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 fr(e){$(k.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 yr(){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 Sr(e){$(k.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 Er(){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 un(e,t,o="global"){let n=dn(t);if(!n||n.id==="none")return;let r=k.join(e,"apps","web");if(!Ge.existsSync(r))return;let i=n.id;try{switch(i){case"posthog":ir(r),ge(e,sr());return;case"plausible":ar(r),ge(e,cr());return;case"umami":pr(r),ge(e,lr());return;case"mixpanel":dr(r),ge(e,ur());return;case"baidu":mr(r),ge(e,gr());return;case"sensors":fr(r),ge(e,yr());return;case"growingio":Sr(r),ge(e,Er());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 hr="https://analytics.nebutra.com";function vr(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function mn(e,t={}){vr(t)||(async()=>{try{let o=await import("./dist-B4YTE2SQ.js");if(typeof o.createAnalyticsClient!="function")return;let n=o.createAnalyticsClient({posthog:{apiKey:process.env.NEBUTRA_POSTHOG_KEY??"",host:process.env.NEBUTRA_POSTHOG_HOST??hr},onError:()=>{}});if(typeof n?.track!="function")return;let r=n.track("scaffold.completed",e);r&&typeof r.then=="function"&&await r.catch(()=>{})}catch{}})()}import U from"fs";import fe from"path";function Ft(e){U.existsSync(e)&&U.rmSync(e,{recursive:!0,force:!0})}function gn(e,t){let o=fe.join(e,".env.example");U.existsSync(o)?U.appendFileSync(o,`
340
- `+t):U.writeFileSync(o,t)}function fn(e,t){if(!U.existsSync(e))return;let o=U.readFileSync(e,"utf8"),n=o.replace(/export type AuthProviderId\s*=\s*"[^"]+"\s*\|\s*"[^"]+";/,`export type AuthProviderId = "${t}";`);n!==o&&U.writeFileSync(e,n)}function _r(e,t){let o=fe.join(e,"README.md");if(!U.existsSync(o)){U.writeFileSync(o,t);return}U.appendFileSync(o,`
341
- `+t)}async function yn(e,t){let o=fe.join(e,"packages","auth");if(!U.existsSync(o))return;if(t==="none"){Ft(o),_r(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
- Auth was skipped at scaffold time (\`--auth=none\`). Add your preferred auth provider manually (e.g. Clerk, Better Auth, NextAuth).
345
- `);return}let n=fe.join(o,"src","providers"),r=fe.join(o,"src","types.ts");if(t==="clerk"){Ft(fe.join(n,"better-auth.ts")),fn(r,"clerk"),gn(e,`# Clerk auth
344
+ Auth was skipped at scaffold time (\`--auth=none\`). Add your preferred auth provider manually (e.g. Clerk, Better 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"){Ft(fe.join(n,"clerk.ts")),fn(r,"better-auth"),gn(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 nt=[{id:"wechat",name:"\u5FAE\u4FE1\u5F00\u653E\u5E73\u53F0",region:"cn",envVars:["WECHAT_APP_ID","WECHAT_APP_SECRET"],docs:"https://open.weixin.qq.com/cgi-bin/showdocument",callbackUrl:"/api/auth/callback/wechat",tokenEndpoint:"https://api.weixin.qq.com/sns/oauth2/access_token"},{id:"qq",name:"QQ \u767B\u5F55",region:"cn",envVars:["QQ_APP_ID","QQ_APP_KEY"],docs:"https://wiki.connect.qq.com",callbackUrl:"/api/auth/callback/qq",tokenEndpoint:"https://graph.qq.com/oauth2.0/token"},{id:"dingtalk",name:"\u9489\u9489",region:"cn",envVars:["DINGTALK_APP_ID","DINGTALK_APP_SECRET"],docs:"https://open.dingtalk.com/document/",callbackUrl:"/api/auth/callback/dingtalk",tokenEndpoint:"https://api.dingtalk.com/v1.0/oauth2/userAccessToken"},{id:"workweixin",name:"\u4F01\u4E1A\u5FAE\u4FE1",region:"cn",envVars:["WORKWEIXIN_CORP_ID","WORKWEIXIN_AGENT_ID","WORKWEIXIN_SECRET"],docs:"https://developer.work.weixin.qq.com",callbackUrl:"/api/auth/callback/workweixin",tokenEndpoint:"https://qyapi.weixin.qq.com/cgi-bin/gettoken"},{id:"feishu",name:"\u98DE\u4E66 / Lark",region:"cn",envVars:["FEISHU_APP_ID","FEISHU_APP_SECRET"],docs:"https://open.feishu.cn/document/",callbackUrl:"/api/auth/callback/feishu",tokenEndpoint:"https://open.feishu.cn/open-apis/authen/v1/access_token"},{id:"weibo",name:"\u5FAE\u535A",region:"cn",envVars:["WEIBO_APP_KEY","WEIBO_APP_SECRET"],docs:"https://open.weibo.com/wiki/",callbackUrl:"/api/auth/callback/weibo",tokenEndpoint:"https://api.weibo.com/oauth2/access_token"}],Pr=new Set(nt.map(e=>e.id));function Sn(e){return nt.find(t=>t.id===e)}function En(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)Pr.has(r)&&!n.has(r)&&(o.push(r),n.add(r));return o}import Se from"fs";import ye from"path";function br(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 Ir(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 hn(e){Se.mkdirSync(e,{recursive:!0})}function Ar(e,t){let o=ye.join(e,".env.example");Se.existsSync(o)?Se.appendFileSync(o,`
520
- `+t):Se.writeFileSync(o,t)}function Cr(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 vn(e,t,o){if(!t||t.length===0)return;let n=ye.join(e,"apps","web");if(!Se.existsSync(n))return;let r=new Set,i=[];for(let d of t){if(r.has(d))continue;r.add(d);let u=Sn(d);u&&i.push(u)}if(i.length===0)return;for(let d of i)Ar(e,Cr(d));let s=ye.join(n,"src","app","api","auth","callback");for(let d of i){let u=ye.join(s,d.id);hn(u);let h=ye.join(u,"route.ts");Se.writeFileSync(h,br(d,o))}let c=ye.join(n,"src","components","auth");hn(c);let a=ye.join(c,"SocialLoginButtons.tsx");Se.writeFileSync(a,Ir(i))}import ne from"fs";import jt from"path";var ht=[{id:"upstash-redis",name:"Upstash Redis",region:"both",envVars:["UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN"],docs:"https://upstash.com/docs/redis",description:"Serverless Redis"},{id:"vercel-kv",name:"Vercel KV",region:"global",envVars:["KV_URL","KV_REST_API_URL","KV_REST_API_TOKEN","KV_REST_API_READ_ONLY_TOKEN"],docs:"https://vercel.com/docs/storage/vercel-kv",description:"Vercel native KV"},{id:"redis",name:"Redis (self-hosted)",region:"both",envVars:["REDIS_URL"],docs:"https://redis.io/docs/",description:"Self-hosted Redis"},{id:"dragonfly",name:"Dragonfly",region:"global",envVars:["DRAGONFLY_URL"],docs:"https://www.dragonflydb.io/docs",description:"Drop-in Redis replacement, faster"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip cache package"}];function _n(e){return ht.find(t=>t.id===e)}var wa=ht.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Pn(e){return ne.existsSync(e)?ne.readFileSync(e,"utf-8"):null}function wr(e,t){let o=jt.join(e,".env.example"),n=Pn(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(`
524
- `);ne.appendFileSync(o,i)}function Rr(e,t,o){let n=jt.join(e,".env.example"),r=Pn(n);if(r===null)return;let i=new RegExp(`^${t}=.*$`,"m");i.test(r)?ne.writeFileSync(n,r.replace(i,`${t}="${o}"`)):ne.appendFileSync(n,`${t}="${o}"
525
- `)}async function bn(e,t,o){let n=jt.join(e,"packages","cache");if(t==="none"){ne.existsSync(n)&&ne.rmSync(n,{recursive:!0,force:!0});return}let r=_n(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${ht.map(i=>i.id).join(", ")}`);ne.existsSync(n)&&(wr(e,r),Rr(e,"CACHE_PROVIDER",t))}var vt=[{id:"turnstile",name:"Cloudflare Turnstile",region:"global",envVars:["NEXT_PUBLIC_TURNSTILE_SITE_KEY","TURNSTILE_SECRET_KEY"],docs:"https://developers.cloudflare.com/turnstile/",description:"Free, privacy-focused captcha alternative"},{id:"hcaptcha",name:"hCaptcha",region:"global",envVars:["NEXT_PUBLIC_HCAPTCHA_SITE_KEY","HCAPTCHA_SECRET_KEY"],docs:"https://docs.hcaptcha.com/",description:"Privacy-respecting captcha"},{id:"aliyun-slide",name:"\u963F\u91CC\u4E91\u9A8C\u8BC1\u7801 2.0",region:"cn",envVars:["ALIYUN_CAPTCHA_ACCESS_KEY_ID","ALIYUN_CAPTCHA_ACCESS_KEY_SECRET","ALIYUN_CAPTCHA_APP_KEY","NEXT_PUBLIC_ALIYUN_CAPTCHA_APP_KEY"],docs:"https://help.aliyun.com/product/28308.html",description:"\u963F\u91CC\u4E91\u667A\u80FD\u9A8C\u8BC1 (\u6ED1\u5757/\u65E0\u75D5)"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function In(e){return vt.find(t=>t.id===e)}var Oa=vt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import J from"fs";import Vt from"path";function q(e,t){let o=Vt.join(e,".env.example");if(!J.existsSync(o)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(J.readFileSync(o,"utf-8").includes(r))return;let c=["","# =============================================",r,t.docs?`# Docs: ${t.docs}`:null,"# =============================================",...t.envVars.map(a=>`${a}=""`),""].filter(a=>a!==null).join(`
526
- `);J.appendFileSync(o,c)}function G(e,t,o){let n=Vt.join(e,".env.example");if(!J.existsSync(n))return;let r=J.readFileSync(n,"utf-8"),i=`${t}="${o}"`,s=new RegExp(`^${t}=.*$`,"m");if(s.test(r)){J.writeFileSync(n,r.replace(s,i));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
- `;J.appendFileSync(n,`${c}${i}
529
- `)}function K(e,t){let o=Vt.join(e,"packages",t);J.existsSync(o)&&J.rmSync(o,{recursive:!0,force:!0})}async function An(e,t,o="global"){let n=In(t);if(!n)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${vt.map(r=>r.id).join(", ")}`);if(n.id==="none"){K(e,"captcha");return}n.envVars.length>0&&q(e,{category:"Captcha",name:n.name,envVars:n.envVars,docs:n.docs}),G(e,"CAPTCHA_PROVIDER",n.id)}import Pt from"fs";import xr from"path";var _t=[{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 Cn(e){return _t.find(t=>t.id===e)}var Ka=_t.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function wn(e,t,o="global"){let n=Cn(t);if(!n)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${_t.map(i=>i.id).join(", ")}`);let r=xr.join(e,"apps","studio");if(n.id==="none"){K(e,"sanity"),Pt.existsSync(r)&&Pt.rmSync(r,{recursive:!0,force:!0});return}n.id!=="sanity"&&(K(e,"sanity"),Pt.existsSync(r)&&Pt.rmSync(r,{recursive:!0,force:!0})),n.envVars.length>0&&q(e,{category:"CMS",name:n.name,envVars:n.envVars,docs:n.docs}),G(e,"CMS_PROVIDER",n.id)}import A from"fs";import I from"path";var Nr=I.join("apps","web"),Kt=I.join("src","components","compliance"),ot=I.join("src","app","[locale]");function H(e){return I.join(e,Nr)}function kr(e){A.mkdirSync(e,{recursive:!0})}function B(e,t){kr(I.dirname(e)),A.writeFileSync(e,t,"utf8")}function Bt(e,t){let o=I.join(e,".env.example");if(A.existsSync(o)){if(A.readFileSync(o,"utf8").includes(t.split(`
530
- `)[0]??""))return;A.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 A.writeFileSync(o,t+`
533
- `)}var rt=`> **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`,Tr=`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
- `,Or=`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
- `,Ur=`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;
@@ -614,7 +622,7 @@ export function Footer({ region = "global" }: FooterProps) {
614
622
  </a>
615
623
  );
616
624
  }
617
- `,Lr=`"use client";
625
+ `,Yr=`"use client";
618
626
 
619
627
  import { useCallback, useEffect, useState } from "react";
620
628
 
@@ -841,7 +849,7 @@ function CategoryRow({ id, title, description, checked, disabled, onChange }: Ca
841
849
  </label>
842
850
  );
843
851
  }
844
- `,Mr=`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
- `,Dr=`---
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
- ${rt}
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
- `,Fr=`---
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
- ${rt}
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
- `,jr=`---
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
- ${rt}
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
- `,Vr=`---
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
- ${rt}
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
- `,Kr=`---
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
- ${rt}
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 Br(e,t){let o=H(e);if(!A.existsSync(o))return;let n=I.join(o,"src","components","compliance","Footer.tsx");B(n,Tr);let r=I.join(o,"src","components","compliance","README.md");B(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 Yr(e,t){let o=H(e);if(!A.existsSync(o))return;let n=I.join(o,"src","components","compliance","CookieBanner.tsx");B(n,Lr)}async function $r(e,t){let o=H(e);if(!A.existsSync(o))return;let n=I.join(o,ot,"privacy","page.mdx");B(n,Dr)}async function qr(e,t){let o=H(e);if(!A.existsSync(o))return;let n=I.join(o,ot,"terms","page.mdx");B(n,Fr)}async function Gr(e){let t=H(e);if(!A.existsSync(t))return;let o=I.join(t,Kt,"IcpFooter.tsx");B(o,Or),Bt(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 Hr(e){let t=H(e);if(!A.existsSync(t))return;let o=I.join(t,Kt,"PublicSecurityFooter.tsx");B(o,Ur),Bt(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 Wr(e){let t=H(e);if(!A.existsSync(t))return;let o=I.join(t,Kt,"AigcDisclaimer.tsx");B(o,Mr),Bt(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 Xr(e){let t=H(e);if(!A.existsSync(t))return;let o=I.join(t,ot,"aigc-disclosure","page.mdx");B(o,jr)}async function zr(e){let t=H(e);if(!A.existsSync(t))return;let o=I.join(t,ot,"cross-border-data","page.mdx");B(o,Vr)}async function Qr(e){let t=H(e);if(!A.existsSync(t))return;let o=I.join(t,ot,"pii-collection","page.mdx");B(o,Kr)}async function Rn(e,t){try{await Br(e,t),await Yr(e,t),await $r(e,t),await qr(e,t),(t==="cn"||t==="hybrid")&&(await Gr(e),await Hr(e),await Wr(e),await Xr(e),await zr(e),await Qr(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 Jr from"fs";import Zr from"path";async function xn(e,t){let o=Zr.join(e,"nebutra.config.json");Jr.writeFileSync(o,JSON.stringify(t,null,2)+`
1322
- `)}import oe from"fs";import Yt from"path";function ei(e){oe.existsSync(e)&&oe.rmSync(e,{recursive:!0,force:!0})}function Nn(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function ti(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function kn(e){let t=e.replace(/^\s*extensions\s*=\s*\[[^\]]*\]\s*\n/gm,"");return t=t.replace(/previewFeatures\s*=\s*\[\s*"postgresqlExtensions"\s*\]\s*\n/g,""),t}function ni(e,t){let o=Yt.join(e,".env.example");oe.existsSync(o)?oe.appendFileSync(o,`
1323
- `+t):oe.writeFileSync(o,t)}async function Tn(e,t,o){let n=Yt.join(e,"packages","db");if(t==="none"){ei(n);return}let r=Yt.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",ni(e,`# Database (${t})
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})
1324
1332
  DATABASE_URL="${i}"
1325
- `),!oe.existsSync(r))return;let s=oe.readFileSync(r,"utf8"),c=s;t==="mysql"?(c=Nn(c,"mysql"),c=kn(c)):t==="sqlite"&&(c=Nn(c,"sqlite"),c=ti(c),c=kn(c)),c!==s&&oe.writeFileSync(r,c)}import it from"fs";import L from"path";import{fileURLToPath as oi}from"url";var ri=oi(import.meta.url),ii=L.dirname(ri);async function On(e,t){if(t==="none")return;let o=L.join(ii,"../../templates/deploy");t==="vercel"?await it.promises.copyFile(L.join(o,"vercel.json"),L.join(e,"vercel.json")):t==="railway"?await it.promises.copyFile(L.join(o,"railway.toml"),L.join(e,"railway.toml")):t==="cloudflare"?await it.promises.copyFile(L.join(o,"wrangler.toml"),L.join(e,"wrangler.toml")):t==="selfhost"&&(await it.promises.copyFile(L.join(o,"docker-compose.yml"),L.join(e,"docker-compose.yml")),await it.promises.copyFile(L.join(o,"Dockerfile.web"),L.join(e,"Dockerfile.web")))}import re from"fs";import Ee from"path";import{fileURLToPath as si}from"url";var ai=si(import.meta.url),Un=Ee.dirname(ai),ci=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml)$/;function pi(e){let t=[Ee.join(Un,"..","templates","docs",e),Ee.join(Un,"..","..","templates","docs",e)];for(let o of t)if(re.existsSync(o))return o;return t[0]}async function Ln(e,t){if(t.framework==="none")return;let o=(t.framework==="fumadocs","fumadocs"),n=pi(o),r=Ee.join(e,"apps","docs");if(!re.existsSync(n))throw new Error(`Docs template not found: ${n}`);Mn(n,r),Dn(r,{"{PRODUCT_NAME}":t.projectName})}function Mn(e,t){re.mkdirSync(t,{recursive:!0});for(let o of re.readdirSync(e,{withFileTypes:!0})){let n=Ee.join(e,o.name),r=Ee.join(t,o.name);o.isDirectory()?Mn(n,r):re.copyFileSync(n,r)}}function Dn(e,t){for(let o of re.readdirSync(e,{withFileTypes:!0})){let n=Ee.join(e,o.name);if(o.isDirectory())Dn(n,t);else if(ci.test(o.name)){let r=re.readFileSync(n,"utf-8");for(let[i,s]of Object.entries(t))r=r.split(i).join(s);re.writeFileSync(n,r)}}}import ve from"fs";import he from"path";var bt=[{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 Fn(e){return bt.find(t=>t.id===e)}var dc=bt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var _e="@nebutra/email";function $t(e,t){ve.mkdirSync(he.dirname(e),{recursive:!0}),ve.writeFileSync(e,t)}function li(e,t){let o=he.join(e,".env.example");ve.existsSync(o)?ve.appendFileSync(o,`
1326
- `+t):ve.writeFileSync(o,t)}function di(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,o=e.envVars.map(n=>`${n}=`).join(`
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 ui=`/**
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 mi(){return`/**
1350
- * @${_e.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 gi(){return`/**
1389
- * @${_e.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 fi(){return`/**
1427
- * @${_e.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 yi(){return`/**
1483
- * @${_e.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 Si(){return`/**
1533
- * @${_e.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 Ei(){return`/**
1581
- * @${_e.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,24 +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 hi(e){switch(e){case"resend":return mi();case"postmark":return gi();case"ses":return fi();case"aliyun-dm":return yi();case"tencent-ses":return Si();case"netease":return Ei();case"none":return`export {};
1619
- `}}function vi(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:_e,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 jn(e,t,o){if(t==="none")return;let n=Fn(t);if(!n)throw new Error(`Unknown email provider "${t}". Valid ids: ${bt.map(s=>s.id).join(", ")}`);let r=he.join(e,"packages","email"),i=he.join(r,"src");ve.existsSync(i)&&ve.rmSync(i,{recursive:!0,force:!0}),$t(he.join(r,"package.json"),vi(n)),$t(he.join(i,"types.ts"),ui),$t(he.join(i,"index.ts"),hi(n.id)),li(e,di(n))}import It from"fs";import Vn from"path";async function Kn(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=Vn.join(e,".env"),r=Vn.join(e,".env.local");!It.existsSync(n)&&!It.existsSync(r)?It.writeFileSync(r,o):It.appendFileSync(r,`
1628
- `+o)}import Yn from"crypto";import st from"fs";import Bn from"path";function Pe(e){return Yn.randomBytes(e).toString("base64").replace(/=+$/,"")}function _i(e){return Yn.randomBytes(e).toString("hex")}function Pi(){return{AUTH_SECRET:Pe(32),NEXTAUTH_SECRET:Pe(32),BETTER_AUTH_SECRET:Pe(32),JWT_SECRET:Pe(32),WEBHOOK_SECRET:_i(16),ENCRYPTION_KEY:Pe(32),API_SECRET_KEY:Pe(32),SESSION_SECRET:Pe(32)}}function bi(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Ii(e,t,o){let n=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=bi(o);return e.replace(n,`${t}="${r}"`)}async function $n(e){let t=Bn.join(e,".env.example"),o=Bn.join(e,".env.local");if(!st.existsSync(t))return null;try{let n=st.readFileSync(t,"utf8"),r=Pi(),s=st.existsSync(o)?st.readFileSync(o,"utf8"):n;for(let c of Object.keys(r))s=Ii(s,c,r[c]);return st.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 At=[{id:"vercel-flags",name:"Vercel Flags SDK",region:"global",envVars:["FLAGS_SECRET"],docs:"https://vercel.com/docs/workflow-collaboration/feature-flags",description:"Native Vercel feature flags"},{id:"growthbook",name:"GrowthBook",region:"both",envVars:["GROWTHBOOK_API_HOST","GROWTHBOOK_CLIENT_KEY","GROWTHBOOK_DECRYPTION_KEY"],docs:"https://docs.growthbook.io",description:"Open-source A/B testing + flags"},{id:"configcat",name:"ConfigCat",region:"global",envVars:["CONFIGCAT_SDK_KEY"],docs:"https://configcat.com/docs/",description:"Feature flag & config management"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function qn(e){return At.find(t=>t.id===e)}var Ic=At.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Gn(e,t,o="global"){let n=qn(t);if(!n)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${At.map(r=>r.id).join(", ")}`);if(n.id==="none"){K(e,"feature-flags");return}n.envVars.length>0&&q(e,{category:"Feature Flags",name:n.name,envVars:n.envVars,docs:n.docs}),G(e,"FEATURE_FLAGS_PROVIDER",n.id)}import{execFileSync as Xn}from"child_process";import x from"fs";import Ai from"os";import ie from"path";import Ci from"ignore";var wi={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 Ri(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function xi(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function zn(e){return/^[0-9a-f]{7,40}$/i.test(e)}function Ni(e,t){let o=`https://github.com/${e}.git`,n=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of n)try{let i=Xn("git",["ls-remote",o,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!i)continue;let[s]=i.split(/\s+/);if(zn(s))return s}catch{}return null}async function ki(e,t){if(zn(t))return t;let o=await fetch(`https://api.github.com/repos/${e}/commits/${encodeURIComponent(t)}`,{headers:{Accept:"application/vnd.github+json","User-Agent":"create-sailor"}});if(!o.ok){let r=Ni(e,t);if(r)return r;throw new Error(`Failed to resolve ${e}@${t} (GitHub API ${o.status})`)}let n=await o.json();if(typeof n.sha!="string"||n.sha.length===0)throw new Error(`GitHub API did not return a commit SHA for ${e}@${t}`);return n.sha}function Qn(e,t,o){let n=x.readdirSync(t,{withFileTypes:!0});for(let r of n){if(r.name==="node_modules"||r.name===".git")continue;let i=ie.join(t,r.name),s=ie.relative(e,i).split(ie.sep).join("/");r.isDirectory()?(o.push(s+"/"),Qn(e,i,o)):o.push(s)}}function Ti(e){let t=ie.join(e,".templateignore");if(!x.existsSync(t))return;let o=x.readFileSync(t,"utf8"),n=Ci().add(o),r=[];Qn(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,d)=>d.split("/").length-a.split("/").length);for(let a of c){let d=ie.join(e,a);try{x.existsSync(d)&&x.rmSync(d,{recursive:!0,force:!0})}catch{}}try{x.existsSync(t)&&x.rmSync(t,{force:!0})}catch{}}async function Hn(e,t){let o=await fetch(e,{headers:{Accept:"application/octet-stream","User-Agent":"create-sailor"}});if(!o.ok)throw new Error(`Failed to download archive (${o.status})`);let n=Buffer.from(await o.arrayBuffer());if(n.byteLength<1024)throw new Error(`Downloaded archive is unexpectedly small (${n.byteLength} bytes)`);x.writeFileSync(t,n);let r=x.statSync(t);if(r.size!==n.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${n.byteLength})`);return r.size}function Wn(e,t){Xn("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function Jn(e){try{let t=x.readdirSync(e);for(let o of t)x.rmSync(ie.join(e,o),{recursive:!0,force:!0})}catch{}}async function Oi(e,t){let o=x.mkdtempSync(ie.join(Ai.tmpdir(),"create-sailor-")),n=ie.join(o,"template.tar.gz");try{let r=await ki(e.repo,e.ref);await Hn(xi(e.repo,r),n),Wn(n,t)}catch(r){if(!e.allowMutableFallback)throw r;Jn(t),await Hn(Ri(e.repo,e.ref),n),Wn(n,t)}finally{x.rmSync(o,{recursive:!0,force:!0})}}async function Zn(e){x.mkdirSync(e,{recursive:!0});let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],n;for(let r of o){let i=wi[r];try{if(await Oi(i,e),i.applyIgnore)try{Ti(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)),Jn(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 be from"fs";import qt from"path";async function eo(e,t){let o=qt.join(e,"packages","mcp");if(t==="off"){be.existsSync(o)&&be.rmSync(o,{recursive:!0,force:!0});let r=qt.join(e,"packages","cli","src","commands","mcp-server.ts");be.existsSync(r)&&be.rmSync(r,{force:!0});return}let n=qt.join(e,".env.example");if(be.existsSync(n)){let r=be.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(`
1632
- `);be.appendFileSync(n,s)}}}import at from"fs";import to from"path";async function no(e,t,o){let n=to.join(e,"packages","metering"),r;if(t==="auto"?r=o!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){at.existsSync(n)&&at.rmSync(n,{recursive:!0,force:!0});return}let i=to.join(e,".env.example");if(!at.existsSync(i))return;let s=at.readFileSync(i,"utf-8"),c="# Metering (usage-based billing)";if(!s.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
- `);at.appendFileSync(i,a)}}import He from"fs";import T from"path";var oo=[{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:""}],Kc=oo.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function ro(e){return oo.find(t=>t.id===e)}function Ui(e){He.mkdirSync(e,{recursive:!0})}function W(e,t){Ui(T.dirname(e)),He.writeFileSync(e,t)}function ct(e,t){let o=T.join(e,".env.example");He.existsSync(o)?He.appendFileSync(o,`
1634
- `+t):He.writeFileSync(o,t)}function Li(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";
1635
1644
 
1636
1645
  Sentry.init({
1637
1646
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
@@ -1674,14 +1683,14 @@ export async function register() {
1674
1683
  }
1675
1684
 
1676
1685
  export { captureRequestError as onRequestError } from "@sentry/nextjs";
1677
- `;W(T.join(e,"sentry.client.config.ts"),t),W(T.join(e,"sentry.server.config.ts"),o),W(T.join(e,"sentry.edge.config.ts"),n),W(T.join(e,"instrumentation.ts"),r)}function Mi(){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
1678
1687
  # Get your DSN from https://sentry.io/settings/projects/<project>/keys/
1679
1688
  SENTRY_DSN=
1680
1689
  NEXT_PUBLIC_SENTRY_DSN=
1681
1690
  SENTRY_ORG=
1682
1691
  SENTRY_PROJECT=
1683
1692
  SENTRY_AUTH_TOKEN=
1684
- `}function Di(e){let t=`/**
1693
+ `}function Gi(e){let t=`/**
1685
1694
  * Next.js instrumentation hook \u2014 wires Datadog APM (dd-trace) into Node runtime.
1686
1695
  * Edge runtime is not supported by dd-trace; only nodejs is initialized.
1687
1696
  */
@@ -1729,7 +1738,7 @@ export function initDatadogRum(): void {
1729
1738
  });
1730
1739
  initialized = true;
1731
1740
  }
1732
- `;W(T.join(e,"instrumentation.ts"),t),W(T.join(e,"src","lib","monitoring","datadog-rum.ts"),o)}function Fi(){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
1733
1742
  # Server APM (dd-trace)
1734
1743
  DD_API_KEY=
1735
1744
  DD_APP_KEY=
@@ -1744,7 +1753,7 @@ NEXT_PUBLIC_DD_SITE=datadoghq.com
1744
1753
  NEXT_PUBLIC_DD_SERVICE=sailor-web
1745
1754
  NEXT_PUBLIC_DD_ENV=production
1746
1755
  NEXT_PUBLIC_DD_VERSION=
1747
- `}function ji(e){let t=`/**
1756
+ `}function Hi(e){let t=`/**
1748
1757
  * Bugsnag server-side initialization.
1749
1758
  * Import this once at the top of your server entrypoint or a shared init module.
1750
1759
  */
@@ -1793,11 +1802,11 @@ export function getBugsnagErrorBoundary() {
1793
1802
  errorBoundary = plugin.createErrorBoundary(React) as typeof errorBoundary;
1794
1803
  return errorBoundary;
1795
1804
  }
1796
- `;W(T.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),W(T.join(e,"src","lib","monitoring","bugsnag.client.tsx"),o)}function Vi(){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
1797
1806
  BUGSNAG_API_KEY=
1798
1807
  NEXT_PUBLIC_BUGSNAG_API_KEY=
1799
1808
  APP_VERSION=
1800
- `}function Ki(e){W(T.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1809
+ `}function zi(e){J(U.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1801
1810
  /**
1802
1811
  * \u963F\u91CC\u4E91 ARMS (Application Real-time Monitoring Service) browser agent.
1803
1812
  * Injects the official JS agent via next/script.
@@ -1818,11 +1827,11 @@ export function ArmsScript() {
1818
1827
  />
1819
1828
  );
1820
1829
  }
1821
- `)}function Bi(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1830
+ `)}function Ji(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1822
1831
  ALIYUN_ARMS_LICENSE_KEY=
1823
1832
  ALIYUN_ARMS_APP_NAME=
1824
1833
  NEXT_PUBLIC_ARMS_PID=
1825
- `}function Yi(e){W(T.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1834
+ `}function Qi(e){J(U.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1826
1835
  /**
1827
1836
  * \u542C\u4E91 Browser Agent (\u524D\u7AEF\u6027\u80FD\u76D1\u63A7).
1828
1837
  * Docs: https://www.tingyun.com/docs
@@ -1840,12 +1849,12 @@ export function TingYunScript() {
1840
1849
  />
1841
1850
  );
1842
1851
  }
1843
- `)}function $i(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1852
+ `)}function Zi(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1844
1853
  TINGYUN_LICENSE_KEY=
1845
1854
  NEXT_PUBLIC_TINGYUN_APP_KEY=
1846
- `}async function io(e,t,o="global"){let n=ro(t);if(!n||n.id==="none")return;let r=T.join(e,"apps","web");if(!He.existsSync(r))return;let i=n.id;try{switch(i){case"sentry":Li(r),ct(e,Mi());return;case"datadog":Di(r),ct(e,Fi());return;case"bugsnag":ji(r),ct(e,Vi());return;case"aliyun-arms":Ki(r),ct(e,Bi());return;case"tingyun":Yi(r),ct(e,$i());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 Ct=[{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 so(e){return Ct.find(t=>t.id===e)}var Hc=Ct.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function ao(e,t,o="global"){let n=so(t);if(!n)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${Ct.map(r=>r.id).join(", ")}`);if(n.id==="none"){K(e,"notifications");return}n.envVars.length>0&&q(e,{category:"Notifications",name:n.name,envVars:n.envVars,docs:n.docs}),G(e,"NOTIFICATIONS_PROVIDER",n.id)}import Gt from"fs";import qi from"path";async function co(e,t){let o=qi.join(e,"package.json");if(Gt.existsSync(o)){let n=Gt.readFileSync(o,"utf8"),r=JSON.parse(n);r.name=t,r.version="0.1.0",Gt.writeFileSync(o,JSON.stringify(r,null,2)+`
1847
- `)}}import Z from"fs";import pt from"path";var Gi=["stripe","lemonsqueezy","chinapay","polar"];function po(e){Z.existsSync(e)&&Z.rmSync(e,{recursive:!0,force:!0})}function Hi(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function Wi(e,t){let o=pt.join(e,".env.example");Z.existsSync(o)?Z.appendFileSync(o,`
1848
- `+t):Z.writeFileSync(o,t)}function Xi(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
1849
1858
  STRIPE_SECRET_KEY=
1850
1859
  STRIPE_WEBHOOK_SECRET=
1851
1860
  `;case"lemon":return`# Lemon Squeezy
@@ -1860,14 +1869,14 @@ CHINAPAY_WECHAT_ENABLED=true
1860
1869
  CHINAPAY_APP_ID=
1861
1870
  CHINAPAY_APP_SECRET=
1862
1871
  CHINAPAY_ALIPAY_ENABLED=true
1863
- `}}async function lo(e,t){let o=pt.join(e,"packages","billing");if(!Z.existsSync(o))return;if(t==="none"){po(o);return}let n=pt.join(o,"src"),r=new Set(Hi(t));for(let s of Gi)r.has(s)||po(pt.join(n,s));let i=pt.join(n,"checkout","types.ts");if(Z.existsSync(i)){let s=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",c=Z.readFileSync(i,"utf8"),a=c.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${s}";`);a!==c&&Z.writeFileSync(i,a)}Wi(e,Xi(t))}import se from"fs";import We from"path";var go=new Set(["siliconflow","volcengine-ark","bailian","moonshot"]),Ht=/@sailor:([^\s*]+)/;function zi(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=>go.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 uo(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function mo(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function fo(e,t){let o=e.split(`
1864
- `),n=[],r=e.includes("#"),i=0;for(;i<o.length;){let s=o[i],c=s.match(Ht);if(!c){n.push(s),i++;continue}let{marker:a,keep:d}=zi(c[1],t);if(a==="registry-entries"){n.push(r?mo(s):uo(s)),i++;continue}if(d){let u=r?mo(s):uo(s);u.trim().length>0&&n.push(u);let h=i+1;for(;h<o.length&&o[h].trim()!==""&&!Ht.test(o[h]);)n.push(o[h]),h++;h<o.length&&o[h].trim()===""&&(n.push(o[h]),h++),i=h}else{let u=i+1;for(;u<o.length&&o[u].trim()!==""&&!Ht.test(o[u]);)u++;u<o.length&&o[u].trim()===""&&u++,i=u}}return Qi(n.join(`
1865
- `),t)}function Qi(e,t){let{providerIds:o,customEndpoint:n}=t,r=new Set;for(let d of o)["openai","anthropic","google","mistral","xai"].includes(d)&&r.add(d),r.add(d.replace(/-/g,"_")),r.add(d);n&&r.add("custom");let i=/createProviderRegistry\(\{([\s\S]*?)\}\)/,s=e.match(i);if(!s)return e;let a=s[1].split(`
1866
- `).filter(d=>{let u=d.trim();if(u===""||u.startsWith("//"))return!0;let h=u.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return h?r.has(h[1]):!0}).join(`
1867
- `);return e.replace(i,`createProviderRegistry({${a}})`)}function Ji(e,t){let o=We.join(t,"registry.ts.template"),n=se.readFileSync(o,"utf-8");return fo(n,e)}function Zi(e,t){let o=We.join(t,".env.example.template"),n=se.readFileSync(o,"utf-8");return fo(n,e)}async function yo(e,t,o){let n=Ji(t,o),r=Zi(t,o),i=We.join(e,"packages/agents/src");await se.promises.mkdir(i,{recursive:!0}),await se.promises.writeFile(We.join(i,"registry.ts"),n),await se.promises.appendFile(We.join(e,".env.example"),`
1868
- `+r);let s={ai:"latest"},{providerIds:c,customEndpoint:a}=t;(c.includes("openai")||a||c.some(u=>go.has(u)))&&(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 d=We.join(e,"package.json");if(se.existsSync(d)){let u=JSON.parse(await se.promises.readFile(d,"utf-8"));u.dependencies||(u.dependencies={});for(let[h,O]of Object.entries(s))u.dependencies[h]=O;await se.promises.writeFile(d,JSON.stringify(u,null,2)+`
1869
- `)}}import g from"fs";import P from"path";function So(e,t){if(!g.existsSync(e))return;let o=g.readdirSync(e);for(let n of o){let r=P.join(e,n);g.statSync(r).isDirectory()?So(r,t):t(r)}}async function Eo(e,t){let o=P.join(e,"package.json");if(!g.existsSync(o))return;let n=JSON.parse(g.readFileSync(o,"utf8"));if(t.orm!=="prisma"){let r=P.join(e,"packages","db");if(g.existsSync(r)){let i=P.join(r,"prisma");g.existsSync(i)&&g.rmSync(i,{recursive:!0,force:!0});let s=P.join(r,"package.json");if(g.existsSync(s)){let a=JSON.parse(g.readFileSync(s,"utf8"));a.dependencies&&delete a.dependencies["@prisma/client"],a.devDependencies&&delete a.devDependencies.prisma,g.writeFileSync(s,JSON.stringify(a,null,2)+`
1870
- `)}let c=P.join(r,"src","index.ts");g.existsSync(c)&&g.writeFileSync(c,`
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(`
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(`
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)+`
1879
+ `)}let c=d.join(r,"src","index.ts");f.existsSync(c)&&f.writeFileSync(c,`
1871
1880
  export const prisma = {} as any;
1872
1881
  export const db = {} as any;
1873
1882
  export type PrismaClient = any;
@@ -1913,7 +1922,7 @@ export type UsageAggregate = any;
1913
1922
  export type UsageLedgerEntry = any;
1914
1923
  export type UsageType = any;
1915
1924
  export type UsageLedgerSource = any;
1916
- `)}n.scripts?.postinstall&&(n.scripts.postinstall=n.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let r=P.join(e,"apps");if(g.existsSync(r)){let i=g.readdirSync(r);for(let s of i){let c=P.join(r,s);if(!g.statSync(c).isDirectory())continue;let a=P.join(c,"src","app");if(!g.existsSync(a))continue;["[lang]","[locale]"].forEach(v=>{let l=P.join(a,v);if(g.existsSync(l)){let R=g.readdirSync(l);for(let mt of R)g.renameSync(P.join(l,mt),P.join(a,mt));g.rmdirSync(l)}}),["src/middleware.ts","middleware.ts"].forEach(v=>{let l=P.join(c,v);g.existsSync(l)&&g.rmSync(l)});let d=P.join(c,"src","lib");g.existsSync(d)||g.mkdirSync(d,{recursive:!0});let u=P.join(d,"mock-i18n.ts");g.writeFileSync(u,`
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,`
1917
1926
  import React from 'react';
1918
1927
  export function useTranslations(namespace?: string): any { return (key: string) => key; }
1919
1928
  export function useLocale() { return 'en'; }
@@ -1931,7 +1940,7 @@ export const useRouter = () => ({ push: (...args: any[]) => {}, replace: (...arg
1931
1940
  export default function createMiddleware(...args: any[]) { return (req: any) => req; }
1932
1941
  export function createNavigation(...args: any[]) { return { Link, redirect, usePathname, useRouter, getPathname: () => '/' }; }
1933
1942
  export function defineRouting<T>(config: T): T { return config; }
1934
- `);let O=P.join(d,"mock-i18n.d.ts");g.writeFileSync(O,`declare module '@/lib/mock-i18n' {
1943
+ `);let x=d.join(l,"mock-i18n.d.ts");f.writeFileSync(x,`declare module '@/lib/mock-i18n' {
1935
1944
  export function useTranslations(namespace?: string): any;
1936
1945
  export function useLocale(): string;
1937
1946
  export const NextIntlClientProvider: React.FC<any>;
@@ -1949,18 +1958,19 @@ export function defineRouting<T>(config: T): T { return config; }
1949
1958
  export function createNavigation(...args: any[]): any;
1950
1959
  export function defineRouting<T>(config: T): T;
1951
1960
  }
1952
- `),g.writeFileSync(P.join(d,"mock-i18n-index.ts"),`
1961
+ `),f.writeFileSync(d.join(l,"mock-i18n-index.ts"),`
1953
1962
  export * from './mock-i18n';
1954
1963
  export { default } from './mock-i18n';
1955
- `);let M=P.join(c,"tsconfig.json");if(g.existsSync(M))try{let v=g.readFileSync(M,"utf8");if(v.includes('"paths": {')){let l=v.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": {
1956
1965
  "next-intl": ["./src/lib/mock-i18n"],
1957
- "next-intl/*": ["./src/lib/mock-i18n"],`);g.writeFileSync(M,l)}}catch{}let D=P.join(c,"src");g.existsSync(D)&&So(D,v=>{if(!v.endsWith(".ts")&&!v.endsWith(".tsx"))return;let l=g.readFileSync(v,"utf8"),R=!1;v.endsWith("src/app/layout.tsx")&&l.includes("../providers")&&(l=l.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),R=!0),l=l.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),l=l.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),l.match(/locale\s*:\s*any/)&&(l=l.replace(/locale\s*:\s*any/g,"locale: string"),R=!0),l.match(/lang\s*:\s*any/)&&(l=l.replace(/lang\s*:\s*any/g,"lang: string"),R=!0),l.match(/requestLocale\s*:\s*any/)&&(l=l.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),R=!0),l.match(/\(locale\s*=\s*(.*)\)/)&&(l=l.replace(/\(locale\s*=\s*(.*)\)/g,"() "),R=!0),l.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(l=l.replace(/export\s+default\s+async\s+function\s+LangLayout\s*\(\s*\{\s*children\s*,\s*params\s*\}\s*:\s*LangLayoutProps\s*\)/g,"export default async function LangLayout({ children }: { children: React.ReactNode })"),R=!0),(v.endsWith("src/app/layout.tsx")||v.endsWith("src/app/sitemap.ts")||v.endsWith("src/app/robots.ts")||v.endsWith("src/components/ui/locale-switcher.tsx")||v.endsWith("src/app/(marketing)/blog/[slug]/page.tsx"))&&(l=l.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),l=l.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),l=l.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),l=l.replace(/\(l\)\s*=>/g,"(l: any) =>"),R=!0),v.endsWith("src/i18n/request.ts")&&(l=l.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),R=!0),(l.match(/locale\s*:/)||l.match(/lang\s*:/))&&(R=!0),R&&g.writeFileSync(v,l)});let Xe=P.join(c,"package.json");if(g.existsSync(Xe)){let v=JSON.parse(g.readFileSync(Xe,"utf8"));v.dependencies&&delete v.dependencies["next-intl"],g.writeFileSync(Xe,JSON.stringify(v,null,2)+`
1958
- `)}}}}g.writeFileSync(o,JSON.stringify(n,null,2)+`
1959
- `)}import{getSchema as es,printSchema as ts}from"@mrleebo/prisma-ast";var ns=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function os(e){return e.type==="comment"&&e.text.trim().startsWith("///")}function rs(e){let t=ns.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 is(e,t){for(let o=t-1;o>=0;o--){let n=e[o];if(n.type==="comment"){let r=rs(n.text);if(r)return{annIndex:o,parsed:r};continue}break}return null}function Wt(e,t){let o=es(e),n=new Set;for(let c=0;c<o.list.length;c++){if(o.list[c].type!=="model")continue;let d=is(o.list,c);if(!d)continue;let u=t[d.parsed.flag];if(u!==void 0&&d.parsed.values.includes(u))n.add(d.annIndex);else{n.add(c);for(let M=c-1;M>=0;M--){let D=o.list[M];if(D.type==="comment"&&os(D)){n.add(M);continue}break}let O=o.list[c+1];O&&O.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 ts({type:"schema",list:i})}import ae from"fs";import Xt from"path";var wt=[{id:"qstash",name:"Upstash QStash",region:"both",envVars:["QSTASH_TOKEN","QSTASH_CURRENT_SIGNING_KEY","QSTASH_NEXT_SIGNING_KEY"],docs:"https://upstash.com/docs/qstash",description:"Serverless HTTP-based queue"},{id:"bullmq",name:"BullMQ",region:"both",envVars:["REDIS_URL"],docs:"https://docs.bullmq.io",description:"Redis-backed job queue"},{id:"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 ho(e){return wt.find(t=>t.id===e)}var up=wt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function vo(e){return ae.existsSync(e)?ae.readFileSync(e,"utf-8"):null}function ss(e,t){let o=Xt.join(e,".env.example"),n=vo(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(`
1960
- `);ae.appendFileSync(o,i)}function as(e,t,o){let n=Xt.join(e,".env.example"),r=vo(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}"
1961
- `)}async function _o(e,t,o){let n=Xt.join(e,"packages","queue");if(t==="none"){ae.existsSync(n)&&ae.rmSync(n,{recursive:!0,force:!0});return}let r=ho(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${wt.map(i=>i.id).join(", ")}`);ae.existsSync(n)&&(ss(e,r),as(e,"QUEUE_PROVIDER",t))}import ce from"fs";import zt from"path";var Rt=[{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 Po(e){return Rt.find(t=>t.id===e)}var Ep=Rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function bo(e){return ce.existsSync(e)?ce.readFileSync(e,"utf-8"):null}function cs(e,t){let o=zt.join(e,".env.example"),n=bo(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(`
1962
- `);ce.appendFileSync(o,i)}function ps(e,t,o){let n=zt.join(e,".env.example"),r=bo(n);if(r===null)return;let i=new RegExp(`^${t}=.*$`,"m");i.test(r)?ce.writeFileSync(n,r.replace(i,`${t}="${o}"`)):ce.appendFileSync(n,`${t}="${o}"
1963
- `)}async function Io(e,t,o){let n=zt.join(e,"packages","search");if(t==="none"){ce.existsSync(n)&&ce.rmSync(n,{recursive:!0,force:!0});return}let r=Po(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${Rt.map(i=>i.id).join(", ")}`);ce.existsSync(n)&&(cs(e,r),ps(e,"SEARCH_PROVIDER",t))}import pe from"fs";import Ie from"path";function ls(e){let t=[Ie.join(e,"packages","db"),Ie.join(e,"apps","web")];for(let o of t){let n=Ie.join(o,"prisma","schema.prisma");if(pe.existsSync(n))return{packageDir:o,seedPath:Ie.join(o,"prisma","seed.ts"),packageJsonPath:Ie.join(o,"package.json")}}return null}function ds(e){try{let t=pe.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 us(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
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)+`
1967
+ `)}}}}f.writeFileSync(o,JSON.stringify(n,null,2)+`
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 {
1964
1974
  const admin = await prisma.user.create({
1965
1975
  data: {
1966
1976
  clerkId: "user_mock_admin",
@@ -1991,7 +2001,7 @@ export { default } from './mock-i18n';
1991
2001
  console.log("\\u2713 Created admin user:", admin.email);
1992
2002
  } catch (err) {
1993
2003
  console.warn("\\u26A0 Admin user creation skipped:", (err as Error).message);
1994
- }`}function ms(e,t){let o=t.has("Tenant"),n=t.has("User"),r=t.has("Project"),i=us(e,n),s=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 }> = [];
1995
2005
  try {
1996
2006
  tenants = await Promise.all([
1997
2007
  prisma.tenant.create({
@@ -2060,12 +2070,12 @@ main()
2060
2070
  .finally(async () => {
2061
2071
  await prisma.$disconnect();
2062
2072
  });
2063
- `}function gs(e){if(pe.existsSync(e))try{let t=pe.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};pe.writeFileSync(e,JSON.stringify(s,null,2)+`
2064
- `)}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 Ao(e,t){let o=ls(e);if(o)try{let n=Ie.join(o.packageDir,"prisma","schema.prisma"),r=ds(n),i=ms(t,r),s=Ie.dirname(o.seedPath);pe.existsSync(s)||pe.mkdirSync(s,{recursive:!0}),pe.writeFileSync(o.seedPath,i),gs(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 le from"fs";import Ae from"path";var xt=[{id:"twilio",name:"Twilio",region:"global",envVars:["TWILIO_ACCOUNT_SID","TWILIO_AUTH_TOKEN","TWILIO_FROM_NUMBER"],docs:"https://www.twilio.com/docs/sms",pkgs:["twilio"]},{id:"messagebird",name:"MessageBird (Bird)",region:"global",envVars:["MESSAGEBIRD_ACCESS_KEY","MESSAGEBIRD_ORIGINATOR"],docs:"https://developers.messagebird.com/api/sms-messaging/",pkgs:["messagebird"]},{id:"plivo",name:"Plivo",region:"global",envVars:["PLIVO_AUTH_ID","PLIVO_AUTH_TOKEN","PLIVO_FROM_NUMBER"],docs:"https://www.plivo.com/docs/sms/",pkgs:["plivo"]},{id:"aliyun-sms",name:"\u963F\u91CC\u4E91\u77ED\u4FE1 Aliyun SMS",region:"cn",envVars:["ALIYUN_SMS_ACCESS_KEY","ALIYUN_SMS_ACCESS_SECRET","ALIYUN_SMS_SIGN_NAME","ALIYUN_SMS_TEMPLATE_CODE","ALIYUN_SMS_ENDPOINT"],docs:"https://help.aliyun.com/product/44282.html",pkgs:["@alicloud/dysmsapi20170525","@alicloud/openapi-client"]},{id:"tencent-sms",name:"\u817E\u8BAF\u4E91\u77ED\u4FE1 Tencent SMS",region:"cn",envVars:["TENCENT_SMS_SECRET_ID","TENCENT_SMS_SECRET_KEY","TENCENT_SMS_SDK_APP_ID","TENCENT_SMS_SIGN_NAME","TENCENT_SMS_TEMPLATE_ID","TENCENT_SMS_REGION"],docs:"https://cloud.tencent.com/document/product/382",pkgs:["tencentcloud-sdk-nodejs-sms"]},{id:"yunpian",name:"\u4E91\u7247 Yunpian",region:"cn",envVars:["YUNPIAN_API_KEY","YUNPIAN_SIGN"],docs:"https://www.yunpian.com/official/document/sms/zh_CN/introduction_product_intro",pkgs:["yunpian-nodejs-sdk"]},{id:"none",name:"None",region:"both",envVars:[],docs:""}],wp=xt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Co(e){return xt.find(t=>t.id===e)}var fs="@nebutra/sms",ys={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 Qt(e,t){le.mkdirSync(Ae.dirname(e),{recursive:!0}),le.writeFileSync(e,t)}function Ss(e,t){let o=Ae.join(e,".env.example");le.existsSync(o)?le.appendFileSync(o,`
2065
- `+t):le.writeFileSync(o,t)}function Es(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(`
2066
2076
  `);return`${t}
2067
2077
  ${o}
2068
- `}var hs=`/**
2078
+ `}var ks=`/**
2069
2079
  * Inputs for the \`sendSms\` wrapper. Keep this surface portable across
2070
2080
  * providers \u2014 provider-specific options belong in the wrapper itself.
2071
2081
  */
@@ -2085,8 +2095,8 @@ export interface SendSmsResult {
2085
2095
  provider: string;
2086
2096
  raw?: unknown;
2087
2097
  }
2088
- `;function vs(){return`import twilio from "twilio";
2089
- import type { SendSmsInput, SendSmsResult } from "./types.js";
2098
+ `;function xs(){return`import twilio from "twilio";
2099
+ import type { SendSmsInput, SendSmsResult } from "./types";
2090
2100
 
2091
2101
  let client: ReturnType<typeof twilio> | null = null;
2092
2102
 
@@ -2119,9 +2129,9 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2119
2129
  return { messageId: message.sid, provider: "twilio", raw: message };
2120
2130
  }
2121
2131
 
2122
- export type { SendSmsInput, SendSmsResult } from "./types.js";
2123
- `}function _s(){return`import messagebird from "messagebird";
2124
- 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";
2125
2135
 
2126
2136
  let client: ReturnType<typeof messagebird> | null = null;
2127
2137
 
@@ -2157,9 +2167,9 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2157
2167
  });
2158
2168
  }
2159
2169
 
2160
- export type { SendSmsInput, SendSmsResult } from "./types.js";
2161
- `}function Ps(){return`import plivo from "plivo";
2162
- 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";
2163
2173
 
2164
2174
  let client: InstanceType<typeof plivo.Client> | null = null;
2165
2175
 
@@ -2196,10 +2206,10 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2196
2206
  };
2197
2207
  }
2198
2208
 
2199
- export type { SendSmsInput, SendSmsResult } from "./types.js";
2200
- `}function bs(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2209
+ export type { SendSmsInput, SendSmsResult } from "./types";
2210
+ `}function Os(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2201
2211
  import * as $OpenApi from "@alicloud/openapi-client";
2202
- import type { SendSmsInput, SendSmsResult } from "./types.js";
2212
+ import type { SendSmsInput, SendSmsResult } from "./types";
2203
2213
 
2204
2214
  let client: Dysmsapi | null = null;
2205
2215
 
@@ -2245,9 +2255,9 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2245
2255
  };
2246
2256
  }
2247
2257
 
2248
- export type { SendSmsInput, SendSmsResult } from "./types.js";
2249
- `}function Is(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2250
- 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";
2251
2261
 
2252
2262
  const SmsClient = tencentcloud.sms.v20210111.Client;
2253
2263
  type SmsClientInstance = InstanceType<typeof SmsClient>;
@@ -2310,10 +2320,10 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2310
2320
  };
2311
2321
  }
2312
2322
 
2313
- export type { SendSmsInput, SendSmsResult } from "./types.js";
2314
- `}function As(){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
2315
2325
  import Yunpian from "yunpian-nodejs-sdk";
2316
- import type { SendSmsInput, SendSmsResult } from "./types.js";
2326
+ import type { SendSmsInput, SendSmsResult } from "./types";
2317
2327
 
2318
2328
  let client: { sms: { single_send(opts: unknown): Promise<unknown>; tpl_single_send(opts: unknown): Promise<unknown> } } | null =
2319
2329
  null;
@@ -2362,14 +2372,14 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2362
2372
  return { provider: "yunpian", raw };
2363
2373
  }
2364
2374
 
2365
- export type { SendSmsInput, SendSmsResult } from "./types.js";
2366
- `}function Cs(e){switch(e){case"twilio":return vs();case"messagebird":return _s();case"plivo":return Ps();case"aliyun-sms":return bs();case"tencent-sms":return Is();case"yunpian":return As();case"none":return`export {};
2367
- `}}function ws(e){let t={};for(let n of e.pkgs??[]){let r=ys[n];r&&(t[n]=r)}let o={name:fs,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)+`
2368
- `}async function wo(e,t,o="global"){if(t==="none")return;let n=Co(t);if(!n)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${xt.map(s=>s.id).join(", ")}`);let r=Ae.join(e,"packages","sms");if(!le.existsSync(r))return;let i=Ae.join(r,"src");le.existsSync(i)&&le.rmSync(i,{recursive:!0,force:!0});try{Qt(Ae.join(r,"package.json"),ws(n)),Qt(Ae.join(i,"types.ts"),hs),Qt(Ae.join(i,"index.ts"),Cs(n.id)),Ss(e,Es(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 we from"fs";import Ce from"path";var lt=[{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 Jt(e){let t=e==="supabase"?"supabase-storage":e;return lt.some(o=>o.id===t)?t:void 0}function Ro(e){let t=Jt(e);return t?lt.find(o=>o.id===t):void 0}var Op=lt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Re="@nebutra/storage";function Zt(e,t){we.mkdirSync(Ce.dirname(e),{recursive:!0}),we.writeFileSync(e,t)}function Rs(e,t){let o=Ce.join(e,".env.example");we.existsSync(o)?we.appendFileSync(o,`
2369
- `+t):we.writeFileSync(o,t)}function xs(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(`
2370
2380
  `);return`${t}
2371
2381
  ${o}
2372
- `}var Ns=`/**
2382
+ `}var Ks=`/**
2373
2383
  * Inputs for the \`uploadFile\` wrapper. Keep this surface portable across
2374
2384
  * providers \u2014 provider-specific options belong in the wrapper itself.
2375
2385
  */
@@ -2395,8 +2405,8 @@ export interface SignedUrlOptions {
2395
2405
  operation?: "get" | "put";
2396
2406
  contentType?: string;
2397
2407
  }
2398
- `;function ks(){return`/**
2399
- * @${Re.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.
2400
2410
  *
2401
2411
  * Docs: https://developers.cloudflare.com/r2/api/s3/api/
2402
2412
  */
@@ -2411,7 +2421,7 @@ import type {
2411
2421
  SignedUrlOptions,
2412
2422
  UploadFileInput,
2413
2423
  UploadFileResult,
2414
- } from "./types.js";
2424
+ } from "./types";
2415
2425
 
2416
2426
  const accountId = process.env.R2_ACCOUNT_ID;
2417
2427
  const accessKeyId = process.env.R2_ACCESS_KEY_ID;
@@ -2458,9 +2468,9 @@ export async function getSignedUrl(
2458
2468
  return awsGetSignedUrl(client, command, { expiresIn });
2459
2469
  }
2460
2470
 
2461
- export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2462
- `}function Ts(){return`/**
2463
- * @${Re.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.
2464
2474
  *
2465
2475
  * Docs: https://docs.aws.amazon.com/s3/
2466
2476
  */
@@ -2475,7 +2485,7 @@ import type {
2475
2485
  SignedUrlOptions,
2476
2486
  UploadFileInput,
2477
2487
  UploadFileResult,
2478
- } from "./types.js";
2488
+ } from "./types";
2479
2489
 
2480
2490
  const region = process.env.AWS_S3_REGION;
2481
2491
  const bucket = process.env.S3_BUCKET;
@@ -2523,9 +2533,9 @@ export async function getSignedUrl(
2523
2533
  return awsGetSignedUrl(client, command, { expiresIn });
2524
2534
  }
2525
2535
 
2526
- export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2527
- `}function Os(){return`/**
2528
- * @${Re.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.
2529
2539
  *
2530
2540
  * Docs: https://supabase.com/docs/guides/storage
2531
2541
  */
@@ -2535,7 +2545,7 @@ import type {
2535
2545
  SignedUrlOptions,
2536
2546
  UploadFileInput,
2537
2547
  UploadFileResult,
2538
- } from "./types.js";
2548
+ } from "./types";
2539
2549
 
2540
2550
  const url = process.env.SUPABASE_URL;
2541
2551
  const serviceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY;
@@ -2586,9 +2596,9 @@ export async function getSignedUrl(
2586
2596
  return data.signedUrl;
2587
2597
  }
2588
2598
 
2589
- export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2590
- `}function Us(){return`/**
2591
- * @${Re.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.
2592
2602
  *
2593
2603
  * Docs: https://help.aliyun.com/product/31815.html
2594
2604
  */
@@ -2598,7 +2608,7 @@ import type {
2598
2608
  SignedUrlOptions,
2599
2609
  UploadFileInput,
2600
2610
  UploadFileResult,
2601
- } from "./types.js";
2611
+ } from "./types";
2602
2612
 
2603
2613
  const accessKeyId = process.env.ALIYUN_OSS_ACCESS_KEY;
2604
2614
  const accessKeySecret = process.env.ALIYUN_OSS_ACCESS_SECRET;
@@ -2633,9 +2643,9 @@ export async function getSignedUrl(
2633
2643
  });
2634
2644
  }
2635
2645
 
2636
- export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2637
- `}function Ls(){return`/**
2638
- * @${Re.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.
2639
2649
  *
2640
2650
  * Docs: https://cloud.tencent.com/document/product/436
2641
2651
  */
@@ -2645,7 +2655,7 @@ import type {
2645
2655
  SignedUrlOptions,
2646
2656
  UploadFileInput,
2647
2657
  UploadFileResult,
2648
- } from "./types.js";
2658
+ } from "./types";
2649
2659
 
2650
2660
  const secretId = process.env.TENCENT_COS_SECRET_ID;
2651
2661
  const secretKey = process.env.TENCENT_COS_SECRET_KEY;
@@ -2688,9 +2698,9 @@ export async function getSignedUrl(
2688
2698
  return url as unknown as string;
2689
2699
  }
2690
2700
 
2691
- export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2692
- `}function Ms(){return`/**
2693
- * @${Re.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.
2694
2704
  *
2695
2705
  * Docs: https://developer.qiniu.com/kodo
2696
2706
  */
@@ -2700,7 +2710,7 @@ import type {
2700
2710
  SignedUrlOptions,
2701
2711
  UploadFileInput,
2702
2712
  UploadFileResult,
2703
- } from "./types.js";
2713
+ } from "./types";
2704
2714
 
2705
2715
  const accessKey = process.env.QINIU_ACCESS_KEY;
2706
2716
  const secretKey = process.env.QINIU_SECRET_KEY;
@@ -2756,10 +2766,10 @@ export async function getSignedUrl(
2756
2766
  return bucketManager.privateDownloadUrl(domain, key, deadline);
2757
2767
  }
2758
2768
 
2759
- export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types.js";
2760
- `}function Ds(e){switch(e){case"r2":return ks();case"s3":return Ts();case"supabase-storage":return Os();case"aliyun-oss":return Us();case"tencent-cos":return Ls();case"qiniu":return Ms();case"none":return`export {};
2761
- `}}function Fs(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:Re,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)+`
2762
- `}async function xo(e,t,o){if(t==="none")return;let n=Ro(t);if(!n)throw new Error(`Unknown storage provider "${t}". Valid ids: ${lt.map(s=>s.id).join(", ")}`);let r=Ce.join(e,"packages","storage"),i=Ce.join(r,"src");we.existsSync(i)&&we.rmSync(i,{recursive:!0,force:!0}),Zt(Ce.join(r,"package.json"),Fs(n)),Zt(Ce.join(i,"types.ts"),Ns),Zt(Ce.join(i,"index.ts"),Ds(n.id)),Rs(e,xs(n))}var Nt=[{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 No(e){return Nt.find(t=>t.id===e)}var jp=Nt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function ko(e,t,o="global"){let n=No(t);if(!n)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Nt.map(r=>r.id).join(", ")}`);if(n.id==="none"){K(e,"webhooks");return}n.envVars.length>0&&q(e,{category:"Webhooks",name:n.name,envVars:n.envVars,docs:n.docs}),G(e,"WEBHOOKS_PROVIDER",n.id)}import xe from"fs";import dt from"path";function js(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";
2763
2773
 
2764
2774
  export default function WelcomePage() {
2765
2775
  const projectName = ${JSON.stringify(e)};
@@ -2868,16 +2878,21 @@ function Step({
2868
2878
  </li>
2869
2879
  );
2870
2880
  }
2871
- `}function Vs(e=[]){return e.length===0?"":`
2881
+ `}function zs(e={}){return`
2882
+ ## What you can do next
2883
+
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(`
2885
+ `)}
2886
+ `}function Js(e=[]){return e.length===0?"":`
2872
2887
  ## Production readiness holds
2873
2888
 
2874
2889
  Do not enable these in production until you replace stubs, add provider credentials, and verify the integration contract:
2875
2890
 
2876
- ${e.map(o=>{let n=qe(o.status);return`- ${o.flag}=${o.provider} ${n} \u2014 ${te(o.status)}`}).join(`
2891
+ ${e.map(o=>{let n=Je(o.status);return`- ${o.flag}=${o.provider} ${n} \u2014 ${se(o.status)}`}).join(`
2877
2892
  `)}
2878
2893
 
2879
2894
  Review the package readiness matrix before handoff: [docs/package-status.md](docs/package-status.md)
2880
- `}function Ks(e,t,o=[]){return`# Next steps \u2014 ${e}
2895
+ `}function Qs(e,t,o=[],n={}){return`# Next steps \u2014 ${e}
2881
2896
 
2882
2897
  Region: ${t}
2883
2898
 
@@ -2903,33 +2918,42 @@ Your AI-native SaaS scaffold is ready. Complete these four steps to go from temp
2903
2918
  \`\`\`
2904
2919
 
2905
2920
  After setup, delete the welcome route at \`apps/web/src/app/[locale]/welcome/\`.
2906
- ${Vs(o)}
2921
+ ${zs(n)}${Js(o)}
2907
2922
 
2908
2923
  ## Resources
2909
2924
 
2910
2925
  - [Documentation](/docs)
2911
2926
  - [GitHub](https://github.com/nebutra/nebutra-sailor)
2912
2927
  - [Get free license (Individual/OPC)](https://nebutra.com/get-license)
2913
- `}async function To(e,t){let{projectName:o,region:n,previewSelections:r=[]}=t;try{let i=dt.join(e,".sailor");xe.existsSync(i)||xe.mkdirSync(i,{recursive:!0}),xe.writeFileSync(dt.join(i,"next-steps.md"),Ks(o,n,r))}catch(i){let s=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write .sailor/next-steps.md: ${s}`)}try{let i=dt.join(e,"apps","web");if(!xe.existsSync(i))return;let s=dt.join(i,"src","app","[locale]","welcome");xe.existsSync(s)||xe.mkdirSync(s,{recursive:!0}),xe.writeFileSync(dt.join(s,"page.tsx"),js(o))}catch(i){let s=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write welcome page: ${s}`)}}var Oo="create-sailor";function p(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2914
- `)}function $s(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function Uo(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 Lo(e){return e==="drizzle"?"drizzle":e==="none"?"none":"prisma"}function Mo(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function Do(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 Fo(e){if(!e)return"clerk";let t=e.toLowerCase();return t==="betterauth"||t==="better-auth"?"betterauth":t==="none"?"none":"clerk"}function jo(e){if(!e)return["openai"];let t=e.split(",").map(o=>o.trim().toLowerCase());return t.includes("none")?[]:t}function qs(e,t){let o=e??t;return Jt(o)??o}var Vo={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function Ko(e,t){if(!e)return"fumadocs";let o=e.toLowerCase();if(o==="fumadocs"||o==="none")return o;if(o in Vo){let n=Vo[o];return t?p(!0,{event:"notice",kind:"docs-fallback",requested:o,effective:"fumadocs"}):process.stdout.write(w.yellow(`\u26A0 ${n} support is coming in v1.2. Falling back to fumadocs.
2915
- `)+w.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
2916
- `)),"fumadocs"}return"fumadocs"}function Bo(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 Yo(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function Gs(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 $o(e){return e==="cn"?"wechat":"stripe"}async function Hs(){let e=new Bs;e.name(Oo).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(ee,"-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("--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&&(an(),process.exit(0));let n=!!t.json,r=!!t.dryRun,i=!!t.yes,s=i||!process.stdin.isTTY;n||on(),p(n,{event:"start",version:ee});let c=o??(i?"./my-saas-app":void 0),a;if(c)a=c;else if(s)a="./my-saas-app";else{let m=await C.group({name:()=>C.text({message:"Where should we create your project?",placeholder:"./my-saas-app",defaultValue:"./my-saas-app",validate:f=>{if(f.length===0)return"Please enter a path."}})},{onCancel:()=>{process.stdout.write(w.red(`\u2718 Cancelled
2917
- `)),process.exit(130)}});a=String(m.name)}let d=ut.basename(ut.resolve(a)),u=t.pm??$s(),h=!!t.region,O=!!t.auth,M=!!t.payment,D=!!t.ai,Xe=!!t.email,v=!!t.storage,l=!!t.monitoring,R=!!t.analytics,mt=!!t.sms,en=t.i18n!==void 0,y,ze,X,Qe,F,N,Y=En(t.socialLogin),Je,Tt,ue,Ne,z,j,gt;if(s){y=Yo(t.region),ze=Lo(t.orm),X=Uo(t.db);let m=M?t.payment:$o(y);Qe=Mo(m),F=Do(m),N=Fo(t.auth);let f=Dt({mode:D?t.ai?.trim().toLowerCase()==="none"?"none":"direct":"gateway",providerIds:D?jo(t.ai):void 0});Je=f.mode,Tt=f.routing,ue=f.providerIds,z=Bo(t.deploy),j=Ko(t.docs,n),gt=en?!!t.i18n:!0}else{let m={};h||(m.region=()=>C.select({message:"Target region?",options:[{value:"global",label:"global \u2014 \u6D77\u5916\u4F18\u5148"},{value:"cn",label:"cn \u2014 \u56FD\u5185\u4F18\u5148"},{value:"hybrid",label:"hybrid \u2014 \u53CC\u8F68\uFF08\u56FD\u5185+\u51FA\u6D77\uFF09"}],initialValue:"global"})),O||(m.auth=()=>C.select({message:"Auth provider?",options:[{value:"clerk",label:"Clerk"},{value:"betterauth",label:"Better Auth"},{value:"none",label:"None"}],initialValue:"clerk"})),D||(m.aiMode=()=>C.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"}),m.aiProviders=({results:E})=>{if(E.aiMode!=="direct")return Promise.resolve([]);let Q=Mt.map(Ut=>({value:Ut.id,label:`[${Ut.category}] ${Ut.name}`}));return C.multiselect({message:"Select direct AI provider adapters (expert path)",options:Q,initialValues:["openai"],required:!1})},m.customAiName=({results:E})=>E.aiMode==="custom"?C.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),m.customAiBaseUrl=({results:E})=>E.aiMode==="custom"?C.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:Q=>{if(Q.length===0)return"Base URL is required."}}):Promise.resolve(void 0),m.customAiApiKeyEnv=({results:E})=>E.aiMode==="custom"?C.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0));let f=Object.keys(m).length>0?await C.group(m,{onCancel:()=>{process.stdout.write(w.red(`\u2718 Cancelled
2918
- `)),process.exit(130)}}):{};y=Yo(h?t.region:f.region),ze=Lo(t.orm),X=Uo(t.db);let V=M?t.payment:$o(y);Qe=Mo(V),F=Do(V),N=Fo(O?t.auth:f.auth);let St=f.aiMode==="custom"?{name:f.customAiName??"custom",baseURL:f.customAiBaseUrl??"",apiKeyEnvName:f.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,S=Dt({mode:D?t.ai?.trim().toLowerCase()==="none"?"none":"direct":f.aiMode??"gateway",providerIds:D?jo(t.ai):f.aiProviders,customEndpoint:St});Je=S.mode,Tt=S.routing,ue=S.providerIds,S.customEndpoint&&(Ne={name:S.customEndpoint.name,baseURL:S.customEndpoint.baseURL,apiKeyEnvName:S.customEndpoint.apiKeyEnvName}),z=Bo(t.deploy),j=Ko(t.docs,n),gt=en?!!t.i18n:!0}let b=Gs(y),ke=Xe?t.email:b.email,Te=qs(v?t.storage:void 0,b.storage),Oe=l?t.monitoring:b.monitoring,Ue=R?t.analytics:b.analytics,Le=mt?t.sms:b.sms,Me=t.queue??b.queue,De=t.search??b.search,Ze=t.cache??b.cache,Fe=t.notifications??b.notifications,je=t.webhooks??b.webhooks,et=t.cms??b.cms,Ve=t.featureFlags??b.featureFlags,Ke=t.captcha??b.captcha,ft=t.mcp??b.mcp,tt=t.metering??b.metering,Be=t.billingMode??b.billingMode,Ye=t.idp??b.idp,$e=rn([{flag:"queue",provider:Me},{flag:"search",provider:De},{flag:"notifications",provider:Fe},{flag:"webhooks",provider:je},{flag:"feature-flags",provider:Ve},{flag:"captcha",provider:Ke}]);function Ot(){for(let m of $e)if(n)p(!0,{event:"warn",step:m.flag,provider:m.provider,packageStatus:m.status,message:te(m.status)});else{let f=qe(m.status);process.stdout.write(w.yellow(`\u26A0 ${m.flag}=${m.provider} ${f} \u2014 ${te(m.status)}
2919
- `))}}let me={region:y,orm:ze,database:X,payment:Qe,aiMode:Je,aiRouting:Tt,aiProviders:ue,customAiEndpoint:Ne,deployTarget:z,docs:j,i18n:gt,email:ke,storage:Te,monitoring:Oe,analytics:Ue,sms:Le,queue:Me,search:De,cache:Ze,notifications:Fe,webhooks:je,cms:et,featureFlags:Ve,captcha:Ke,mcp:ft,metering:tt,billingMode:Be,idp:Ye},yt=[["Project name",d],["Region",y],["Auth",N],["Social login",Y.length>0?Y.map(m=>nt.find(f=>f.id===m)?.name??m).join(", "):"none"],["ORM",ze],["Database",X],["Payment",F],["AI topology",`${Je}${ue.length>0?` (${ue.join(", ")} seed)`:""}${Ne?" + custom endpoint":""}`],["Email",ke],["Storage",Te],["Monitoring",Oe],["Analytics",Ue],["SMS",Le],["Deploy Target",z],["Docs Framework",j]];n?yt.forEach(([m,f],V)=>{p(!0,{event:"step",step:m,value:f,index:V+1,total:yt.length})}):yt.forEach(([m,f],V)=>{pn({index:V+1,total:yt.length,label:m,value:f})});let qo={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""},tn=Date.now();if(r){let m=ue.length,f=[`clone template \u2192 ${a}`,"write nebutra.config.json",`prune template (orm=${ze}, i18n=${gt})`,`region \u2192 ${y}`,`auth \u2192 ${N==="none"?"skip (remove packages/auth)":`configure ${N}`}`,...Y.length>0?[`social-login \u2192 generate ${Y.length} callback route${Y.length===1?"":"s"} + SocialLoginButtons.tsx (${Y.join(", ")})`]:[],`db \u2192 ${X==="none"?"skip (remove packages/db)":`configure Prisma for ${X}`}`,`payment \u2192 ${F==="none"?"skip (remove packages/billing)":`configure ${F}`}`,...j!=="none"?[`docs \u2192 scaffold apps/docs (${j==="fumadocs"?"fumadocs":`${j} \u2192 fumadocs fallback`})`]:[],...m>0||Ne?[`ai-providers \u2192 generate ${Je} registry seed + env (${m}${Ne?" + custom":""} provider${m===1&&!Ne?"":"s"})`]:[],...ke!=="none"?[`email \u2192 configure ${ke}`]:[],...Te!=="none"?[`storage \u2192 configure ${Te}`]:[],...Oe!=="none"?[`monitoring \u2192 configure ${Oe}`]:[],...Ue!=="none"?[`analytics \u2192 configure ${Ue}`]:[],...Le!=="none"?[`sms \u2192 configure ${Le}`]:[],...Me!=="none"?[`queue \u2192 configure ${Me}`]:[],...De!=="none"?[`search \u2192 configure ${De}`]:[],...Ze!=="none"?[`cache \u2192 configure ${Ze}`]:[],...Fe!=="none"?[`notifications \u2192 configure ${Fe}`]:[],...je!=="none"?[`webhooks \u2192 configure ${je}`]:[],...et!=="none"?[`cms \u2192 configure ${et}`]:[],...Ve!=="none"?[`feature-flags \u2192 configure ${Ve}`]:[],...Ke!=="none"?[`captcha \u2192 configure ${Ke}`]:[],`mcp \u2192 ${ft==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${tt==="off"?"disabled":tt==="auto"?Qe!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...Be!=="usage"?[`billing-mode \u2192 ${Be}`]:[],...Ye!=="clerk"?[`idp \u2192 ${Ye}`]:[],`compliance \u2192 inject ${y} 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 ${u} install`,t.git===!1?"skip git init":"run git init"];if(n){for(let V of f)p(!0,{event:"plan",action:V});Ot(),p(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2920
- `+w.bold(`Dry run \u2014 planned actions:
2921
- `));for(let V of f)process.stdout.write(` \u2022 ${V}
2922
- `);$e.length>0&&(process.stdout.write(`
2923
- `+w.bold(w.yellow(`Preview-status providers selected:
2924
- `))),Ot()),process.stdout.write(w.dim(`
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:
2945
+ `));for(let B of S)process.stdout.write(` \u2022 ${B}
2946
+ `);ze.length>0&&(process.stdout.write(`
2947
+ `+C.bold(C.yellow(`Preview-status providers selected:
2948
+ `))),Ft()),process.stdout.write(C.dim(`
2925
2949
  No files were written.
2926
- `))}process.exit(0)}let Go=async()=>{process.stdout.write(`
2927
- `+w.red(`\u2718 Cancelled
2928
- `)),de.existsSync(a)&&await C.confirm({message:`Cleanup partial install at ${a}?`,initialValue:!0})===!0&&(de.rmSync(a,{recursive:!0,force:!0}),process.stdout.write(w.dim(` \u2713 Removed ${a}
2929
- `))),process.exit(130)};process.on("SIGINT",Go);try{p(n,{event:"step",step:"clone",status:"start"}),await Zn(a),p(n,{event:"step",step:"clone",status:"ok"}),p(n,{event:"step",step:"package",status:"start"}),await co(a,d),p(n,{event:"step",step:"package",status:"ok"}),p(n,{event:"step",step:"config",status:"start"}),await xn(a,me),p(n,{event:"step",step:"config",status:"ok"}),p(n,{event:"step",step:"prune",status:"start"}),await Eo(a,me),p(n,{event:"step",step:"prune",status:"ok"});let m=ut.join(a,"packages/db/prisma/schema.prisma");if(de.existsSync(m)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let S=de.readFileSync(m,"utf-8"),E=Wt(S,{auth:N,payment:F,"billing-mode":Be,idp:Ye,template:"saas"});de.writeFileSync(m,E),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(S){let E=S instanceof Error?S.message:String(S);p(n,{event:"step",step:"schema-prune",status:"error",error:E})}}else p(n,{event:"step",step:"schema-prune",status:"skip"});if(p(n,{event:"step",step:"auth",choice:N,status:"start"}),await yn(a,N),p(n,{event:"step",step:"auth",choice:N,status:"ok"}),Y.length>0?(p(n,{event:"step",step:"social-login",providers:Y,status:"start"}),await vn(a,Y,N),p(n,{event:"step",step:"social-login",providers:Y,status:"ok"})):p(n,{event:"step",step:"social-login",status:"skip"}),p(n,{event:"step",step:"db",choice:X,status:"start"}),await Tn(a,X,d),p(n,{event:"step",step:"db",choice:X,status:"ok"}),p(n,{event:"step",step:"payment",choice:F,status:"start"}),await lo(a,F),p(n,{event:"step",step:"payment",choice:F,status:"ok"}),await jn(a,ke,y),n&&p(!0,{event:"step",step:"email",choice:ke,status:"ok"}),await xo(a,Te,y),n&&p(!0,{event:"step",step:"storage",choice:Te,status:"ok"}),await io(a,Oe,y),n&&p(!0,{event:"step",step:"monitoring",choice:Oe,status:"ok"}),await un(a,Ue,y),n&&p(!0,{event:"step",step:"analytics",choice:Ue,status:"ok"}),await wo(a,Le,y),n&&p(!0,{event:"step",step:"sms",choice:Le,status:"ok"}),await _o(a,Me,y),n&&p(!0,{event:"step",step:"queue",choice:Me,status:"ok"}),await Io(a,De,y),n&&p(!0,{event:"step",step:"search",choice:De,status:"ok"}),await bn(a,Ze,y),n&&p(!0,{event:"step",step:"cache",choice:Ze,status:"ok"}),await ao(a,Fe,y),n&&p(!0,{event:"step",step:"notifications",choice:Fe,status:"ok"}),await ko(a,je,y),n&&p(!0,{event:"step",step:"webhooks",choice:je,status:"ok"}),await wn(a,et,y),n&&p(!0,{event:"step",step:"cms",choice:et,status:"ok"}),await Gn(a,Ve,y),n&&p(!0,{event:"step",step:"feature-flags",choice:Ve,status:"ok"}),await An(a,Ke,y),n&&p(!0,{event:"step",step:"captcha",choice:Ke,status:"ok"}),await eo(a,ft),n&&p(!0,{event:"step",step:"mcp",mode:ft,status:"ok"}),await no(a,tt,Qe),n&&p(!0,{event:"step",step:"metering",mode:tt,status:"ok"}),me.orm==="prisma"&&me.database!=="none"){let S=ut.join(a,"packages/db/prisma/schema.prisma");if(de.existsSync(S)){p(n,{event:"step",step:"schema-prune",status:"start"});try{let E=de.readFileSync(S,"utf8"),Q=Wt(E,{auth:N,payment:F,"billing-mode":Be,idp:Ye,template:"saas"});de.writeFileSync(S,Q),p(n,{event:"step",step:"schema-prune",status:"ok"})}catch(E){let Q=E instanceof Error?E.message:String(E);p(n,{event:"step",step:"schema-prune",status:"error",error:Q})}}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:Be,status:"ok"}),p(n,{event:"step",step:"idp",choice:Ye,status:"ok"}),await Rn(a,y),n&&p(!0,{event:"step",step:"compliance",region:y,status:"ok"}),await $n(a),await Ao(a,N),await To(a,{projectName:d,region:y,previewSelections:$e}),me.aiMode!=="none"){p(n,{event:"step",step:"ai-providers",status:"start"});let S={providerIds:me.aiProviders,customEndpoint:me.customAiEndpoint},E=ut.join(a,"packages/ai-providers/templates");await yo(a,S,E),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"}),j!=="none"?(await Ln(a,{framework:j,projectName:d}),p(n,{event:"step",step:"docs",framework:"fumadocs",requested:j,status:"ok"})):p(n,{event:"step",step:"docs",status:"skip"}),p(n,{event:"step",step:"deploy-target",status:"start"}),z!=="none"&&await On(a,z),p(n,{event:"step",step:"deploy-target",status:"ok"}),p(n,{event:"step",step:"env",status:"start"}),await Kn(a,qo),p(n,{event:"step",step:"env",status:"ok"}),t.install!==!1){let S=u==="bun"?"bun install":`${u} install`;n?p(!0,{event:"step",step:"install",pm:u,status:"start"}):process.stdout.write(w.dim(` Installing dependencies with ${u}\u2026
2930
- `));try{kt(S,{cwd:a,stdio:n?"ignore":"inherit"}),p(n,{event:"step",step:"install",status:"ok"})}catch(E){let Q=E instanceof Error?E.message:String(E);n?p(!0,{event:"step",step:"install",status:"error",error:Q}):process.stdout.write(w.yellow(` \u26A0 install failed \u2014 run '${S}' manually.
2931
- `))}}else p(n,{event:"step",step:"install",status:"skip"});if(t.git!==!1){n&&p(!0,{event:"step",step:"git-init",status:"start"});try{kt("git init -q",{cwd:a,stdio:"ignore"}),kt("git add -A",{cwd:a,stdio:"ignore"}),kt('git -c user.email=you@example.com -c user.name="You" commit -q -m "chore: initial scaffold from create-sailor"',{cwd:a,stdio:"ignore"}),p(n,{event:"step",step:"git-init",status:"ok"})}catch(S){let E=S instanceof Error?S.message:String(S);n?p(!0,{event:"step",step:"git-init",status:"error",error:E}):process.stdout.write(w.yellow(` \u26A0 git init skipped \u2014 not fatal.
2932
- `))}}else p(n,{event:"step",step:"git-init",status:"skip"});let St=Math.max(1,Math.round((Date.now()-tn)/1e3));mn({template_version:ee,package_manager:u,region:y,auth:N,payment:F,ai_providers:ue,deploy_target:z,duration_ms:Date.now()-tn}),$e.length>0&&Ot(),n?p(!0,{event:"done",status:"ok",elapsedSec:St,targetDir:a,previewSelections:$e}):sn({elapsedSec:St,targetDir:a,skippedInstall:t.install===!1,previewSelections:$e});try{Ys({pkg:{name:Oo,version:ee},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}process.exit(0)}catch(m){let f=m instanceof Error?m.message:String(m);n?p(!0,{event:"error",message:f}):process.stdout.write(w.red(`
2933
- \u2718 Failed: ${f}
2934
- `)),process.exit(1)}}Hs().catch(e=>{process.stderr.write(String(e)+`
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(`
2957
+ \u2718 Failed: ${S}
2958
+ `)),process.exit(1)}}ra().catch(e=>{process.stderr.write(String(e)+`
2935
2959
  `),process.exit(1)});