create-sailor 1.8.0 → 1.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +2 -2
  2. package/dist/aws-kms-3GX7ZOSJ.js +1 -0
  3. package/dist/{chunk-4AGDXYPL.js → chunk-5ECPN42W.js} +1 -1
  4. package/dist/chunk-FNDUJLS6.js +1 -0
  5. package/dist/chunk-HGJYEXMU.js +1 -0
  6. package/dist/chunk-HX3EZBGO.js +30 -0
  7. package/dist/chunk-IYWUY3VA.js +1 -0
  8. package/dist/chunk-JTXBZ2SU.js +1 -0
  9. package/dist/{chunk-M3QJPQWS.js → chunk-KRX2KWWT.js} +1 -1
  10. package/dist/chunk-OIQB5F6Y.js +1 -0
  11. package/dist/chunk-P2WEIQRQ.js +3 -0
  12. package/dist/chunk-RH2FFVSB.js +1 -0
  13. package/dist/chunk-STX7THHW.js +21 -0
  14. package/dist/chunk-TW5BOTVX.js +0 -0
  15. package/dist/chunk-VFREGXHN.js +1 -0
  16. package/dist/chunk-W5TBFCWY.js +4 -0
  17. package/dist/chunk-WJLTO7JW.js +0 -0
  18. package/dist/chunk-WU3IV4WF.js +1 -0
  19. package/dist/{chunk-UU4YUKYZ.js → chunk-XE3I3HCZ.js} +1 -1
  20. package/dist/chunk-ZIBRKYXP.js +23 -0
  21. package/dist/credits-HWAYRMKF.js +2635 -0
  22. package/dist/{dist-V6L2DNL2.js → dist-B346V4U6.js} +2 -2
  23. package/dist/dist-UXDXDLES.js +1 -0
  24. package/dist/dist-es-B5M7V6O6.js +1 -0
  25. package/dist/{dist-es-JATELSE4.js → dist-es-FU66ZQS5.js} +1 -1
  26. package/dist/dist-es-KE65J6GC.js +1 -0
  27. package/dist/dist-es-PFLN3FTL.js +5 -0
  28. package/dist/dist-es-U3NYQORW.js +1 -0
  29. package/dist/dist-es-VG3XXJ7M.js +2 -0
  30. package/dist/dist-es-WAHVDQ3F.js +2 -0
  31. package/dist/{event-streams-IPTOYMEP.js → event-streams-BXAP5G2H.js} +1 -1
  32. package/dist/event-streams-SGW54BDO.js +1 -0
  33. package/dist/index.js +184 -185
  34. package/dist/loadSso-WRXP2HXL.js +1 -0
  35. package/dist/local-6WWVOMA7.js +1 -0
  36. package/dist/{query_compiler_fast_bg.postgresql-FOSFFKA5.js → query_compiler_fast_bg.postgresql-JA2BFVW5.js} +1 -1
  37. package/dist/{query_compiler_fast_bg.postgresql.wasm-base64-JU7X67WB.js → query_compiler_fast_bg.postgresql.wasm-base64-URHQ2Y3Y.js} +1 -1
  38. package/dist/signin-JB7STGTR.js +1 -0
  39. package/dist/sso-oidc-LTNOJMPI.js +1 -0
  40. package/dist/sts-RKUL4Q47.js +5 -0
  41. package/package.json +1 -1
  42. package/templates/deploy/Dockerfile.web +1 -1
  43. package/dist/aws-kms-EYG3LGYA.js +0 -1
  44. package/dist/chunk-224RJRPV.js +0 -5
  45. package/dist/chunk-2YUF6TO6.js +0 -2
  46. package/dist/chunk-76FD5Z7D.js +0 -23
  47. package/dist/chunk-7OZT53MS.js +0 -1
  48. package/dist/chunk-AAIUIEEA.js +0 -1
  49. package/dist/chunk-C6CKWQY5.js +0 -20
  50. package/dist/chunk-CHWVD37K.js +0 -1
  51. package/dist/chunk-EBTFPGDR.js +0 -9
  52. package/dist/chunk-EIQ2HSZP.js +0 -1
  53. package/dist/chunk-FSRPMVAS.js +0 -1
  54. package/dist/chunk-IY2KKEUD.js +0 -1
  55. package/dist/chunk-OWZF7P72.js +0 -1
  56. package/dist/chunk-WI7DO2VU.js +0 -1
  57. package/dist/chunk-XPRSUMI6.js +0 -1
  58. package/dist/credits-7FJY7HK2.js +0 -2613
  59. package/dist/dist-LOLT3W3R.js +0 -1
  60. package/dist/dist-es-3AHFNYTD.js +0 -5
  61. package/dist/dist-es-6KZILXYZ.js +0 -1
  62. package/dist/dist-es-H627TNCU.js +0 -1
  63. package/dist/dist-es-I6TTSEP7.js +0 -2
  64. package/dist/dist-es-NRANDF25.js +0 -2
  65. package/dist/dist-es-YSAFQMS4.js +0 -1
  66. package/dist/loadSso-FR7LG5FX.js +0 -1
  67. package/dist/local-BUKM6VCO.js +0 -1
  68. package/dist/signin-N4XQB5ZB.js +0 -1
  69. package/dist/sso-oidc-FXPYRI5I.js +0 -1
  70. package/dist/sts-SIEJPPW3.js +0 -6
  71. /package/dist/{chunk-3T4EOSMQ.js → chunk-SPHQRDN5.js} +0 -0
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import"./chunk-FSRPMVAS.js";import{execSync as jc}from"child_process";import Vs from"fs";import Ks from"path";import*as nt from"@clack/prompts";import F from"picocolors";import{Command as Hs}from"commander";import In from"fs";import Vt from"path";import{fileURLToPath as qs}from"url";function Gs(){try{let t=Vt.dirname(qs(import.meta.url));for(let n=0;n<4;n++){let o=Vt.join(t,"package.json");if(In.existsSync(o)){let s=In.readFileSync(o,"utf-8"),r=JSON.parse(s);if(r.name==="create-sailor"&&typeof r.version=="string")return r.version}t=Vt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var X=Gs();var Ws="create-sailor";function Cn(){let e=new Hs;return e.name(Ws).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(X,"-v, --version").helpOption(!1).argument("[name]","project directory",void 0).option("-p, --pm <id>","npm | pnpm | yarn | bun").option("--region <id>","global | cn | hybrid").option("--orm <id>","prisma (default, primary) | drizzle (dual-ORM: adds db-drizzle alongside Prisma \u2014 Postgres only)").option("--db <id>","postgres | mysql | sqlite | none \u2014 engine (Prisma provider)").option("--db-host <id>","local | supabase | neon | vercel-postgres | planetscale | railway | aliyun-rds | tencent-cdb | none \u2014 managed-provider (region default: supabase global, local cn)").option("--auth <id>","clerk | betterauth | nextauth | supabase | none").option("--social-login <ids>","CN social login providers \u2014 wechat | qq | dingtalk | workweixin | feishu | weibo (comma-separated)").option("--payment <id>","stripe | lemon | wechat | alipay | none").option("--ai <mode-or-ids>","topology shorthand (gateway | direct | custom | none) OR comma-separated provider ids (e.g. openai,anthropic)").option("--deploy <target>","vercel | railway | cloudflare | selfhost").option("--docs <id>","fumadocs | mintlify | docusaurus | nextra | vitepress | none").option("--email <id>","resend | postmark | ses | aliyun-dm | tencent-ses | netease | none").option("--storage <id>","r2 | s3 | supabase-storage | aliyun-oss | tencent-cos | qiniu | none").option("--monitoring <id>","sentry | datadog | aliyun-arms | tingyun | none").option("--analytics <id>","posthog | plausible | umami | baidu | sensors | none").option("--sms <id>","twilio | aliyun-sms | tencent-sms | yunpian | none").option("--queue <id>","qstash | bullmq | sqs | none").option("--search <id>","meilisearch | typesense | algolia | pgvector | none").option("--cache <id>","upstash-redis | vercel-kv | redis | dragonfly | none").option("--notifications <id>","novu | knock | custom | none").option("--webhooks <id>","svix | custom | none").option("--cms <id>","sanity | contentful | strapi | none").option("--feature-flags <id>","vercel-flags | growthbook | configcat | none").option("--captcha <id>","turnstile | hcaptcha | aliyun-slide | none").option("--mcp <mode>","on | off (default: on)").option("--metering <mode>","auto | on | off (default: auto \u2014 auto-on when payment is set)").option("--billing-mode <mode>","usage | seat | credits (default: usage)").option("--idp <id>","clerk | oauth-server (default: clerk)").option("--access-gate <mode>","none | invite (default: none)").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: false \u2014 @nebutra/audit is WIP)").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("--with-workflows","scaffold workflows/ (inngest + n8n + pusher stubs)").option("--with-python-backend","scaffold backends/python/ (FastAPI stub \u2014 only when TS-by-Default ADR exception applies)").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}import kn from"picocolors";var Kt=[{id:"local",name:"Local / Self-hosted Docker",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres:postgres@localhost:5432/$PROJECT",comment:"Local Postgres via docker-compose (pnpm infra:up)"}],docs:"https://www.postgresql.org/docs/",description:"Docker on localhost. You operate it.",tier:"self-hosted"},{id:"supabase",name:"Supabase",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:5432/postgres?sslmode=require",comment:"Supabase session pooler \u2014 use for runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://postgres:<password>@db.<project-ref>.supabase.co:5432/postgres?sslmode=require",comment:"Supabase direct \u2014 use for Prisma migrations"},{name:"NEXT_PUBLIC_SUPABASE_URL",placeholder:"https://<project>.supabase.co"},{name:"NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY",placeholder:""},{name:"NEXT_PUBLIC_SUPABASE_ANON_KEY",placeholder:""},{name:"SUPABASE_PUBLISHABLE_KEY",placeholder:""},{name:"SUPABASE_SERVICE_ROLE_KEY",placeholder:""}],docs:"https://supabase.com/docs",description:"Managed Postgres + auth/storage/realtime/edge-functions.",tier:"managed"},{id:"neon",name:"Neon",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>-pooler.<region>.neon.tech/<db>?sslmode=require",comment:"Neon pooled \u2014 runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>.<region>.neon.tech/<db>?sslmode=require",comment:"Neon direct (no -pooler) \u2014 migrations"}],docs:"https://neon.tech/docs",description:"Serverless Postgres with branching and scale-to-zero.",tier:"managed"},{id:"vercel-postgres",name:"Vercel Postgres",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"$POSTGRES_PRISMA_URL",comment:"Vercel Marketplace injects POSTGRES_PRISMA_URL automatically"},{name:"DIRECT_URL",placeholder:"$POSTGRES_URL_NON_POOLING",comment:"Vercel Marketplace injects POSTGRES_URL_NON_POOLING automatically"}],docs:"https://vercel.com/docs/storage/vercel-postgres",description:"Neon-backed, auto-provisioned via Vercel Marketplace.",tier:"managed"},{id:"planetscale",name:"PlanetScale",region:"global",supportedEngines:["mysql"],forcedEngine:"mysql",prismaDatasourceExtras:['relationMode = "prisma"'],envVars:[{name:"DATABASE_URL",placeholder:"mysql://<user>:<pass>@<host>.psdb.cloud/<db>?sslaccept=strict",comment:'PlanetScale: relationMode = "prisma" (no FK support server-side)'}],docs:"https://planetscale.com/docs",description:"Managed MySQL with branching. No foreign keys.",tier:"managed"},{id:"railway",name:"Railway",region:"global",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"$DATABASE_URL",comment:"Railway service env var; injected when you link a Postgres service"}],docs:"https://docs.railway.app/databases/postgresql",description:"Generalist managed infra; standard TCP Postgres/MySQL.",tier:"managed"},{id:"aliyun-rds",name:"Aliyun RDS",region:"cn",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@<rds-instance>.rds.aliyuncs.com:5432/<db>",comment:"Aliyun RDS Postgres \u2014 internal VPC endpoint recommended"}],docs:"https://www.alibabacloud.com/help/en/rds",description:"Aliyun RDS \u2014 China compliance + intranet routing.",tier:"managed"},{id:"tencent-cdb",name:"Tencent CloudDB (CDB)",region:"cn",supportedEngines:["mysql","postgresql"],envVars:[{name:"DATABASE_URL",placeholder:"mysql://<user>:<pwd>@<cdb-instance>.tencentcdb.com:3306/<db>",comment:"Tencent CloudDB \u2014 VPC endpoint recommended"}],docs:"https://intl.cloud.tencent.com/document/product/236",description:"Tencent CloudDB \u2014 China compliance.",tier:"managed"},{id:"none",name:"None",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[],docs:"",description:"Skip database scaffolding.",tier:"self-hosted"}];function st(e){return Kt.find(t=>t.id===e)}function xn(e){return e==="cn"||e==="hybrid"?"local":"supabase"}var rt=[{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 $t(e){let t=e==="supabase"?"supabase-storage":e;return rt.some(n=>n.id===t)?t:void 0}function Rn(e){let t=$t(e);return t?rt.find(n=>n.id===t):void 0}var zc=rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Nn(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function Yt(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 qt(e,t,n){let o=e?.trim().toLowerCase()??xn(t),s=st(o);if(!s){let i=Kt.map(a=>a.id).join(", ");throw new Error(`Unknown --db-host="${o}". Valid: ${i}`)}let r=n;return s.forcedEngine&&r!=="none"&&r!==s.forcedEngine&&(r=s.forcedEngine),{hostId:s.id,engine:r}}function Gt(e){return e==="drizzle"?"drizzle":"prisma"}function Ht(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function Wt(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 Xt(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==="supabase"||t==="supabase-auth"?"supabase":t==="none"?"none":"clerk"}var Xs=new Set(["gateway","direct","custom","none"]);function zt(e){if(!e)return!1;let t=e.trim().toLowerCase();return Xs.has(t)}function Jt(e){if(!e)return["openai"];if(zt(e))return[];let t=e.split(",").map(n=>n.trim().toLowerCase());return t.includes("none")?[]:t}function On(e,t){let n=e??t;return $t(n)??n}var Tn={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function Qt(e,t){if(!e)return"fumadocs";let n=e.toLowerCase();if(n==="fumadocs"||n==="none")return n;if(n in Tn){let o=Tn[n];return t?process.stdout.write(JSON.stringify({event:"notice",kind:"docs-fallback",requested:n,effective:"fumadocs"})+`
2
+ import"./chunk-IYWUY3VA.js";import{execSync as Vc}from"child_process";import Vr from"fs";import Kr from"path";import*as ot from"@clack/prompts";import F from"picocolors";import{Command as Hr}from"commander";import In from"fs";import Vt from"path";import{fileURLToPath as qr}from"url";function Gr(){try{let t=Vt.dirname(qr(import.meta.url));for(let n=0;n<4;n++){let o=Vt.join(t,"package.json");if(In.existsSync(o)){let r=In.readFileSync(o,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=Vt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var X=Gr();var Wr="create-sailor";function Cn(){let e=new Hr;return e.name(Wr).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(X,"-v, --version").helpOption(!1).argument("[name]","project directory",void 0).option("-p, --pm <id>","npm | pnpm | yarn | bun").option("--region <id>","global | cn | hybrid").option("--orm <id>","prisma (default, primary) | drizzle (dual-ORM: adds db-drizzle alongside Prisma \u2014 Postgres only)").option("--db <id>","postgres | mysql | sqlite | none \u2014 engine (Prisma provider)").option("--db-host <id>","local | supabase | neon | vercel-postgres | planetscale | railway | aliyun-rds | tencent-cdb | none \u2014 managed-provider (region default: supabase global, local cn)").option("--auth <id>","clerk | betterauth | nextauth | supabase | none").option("--social-login <ids>","CN social login providers \u2014 wechat | qq | dingtalk | workweixin | feishu | weibo (comma-separated)").option("--payment <id>","stripe | lemon | wechat | alipay | none").option("--ai <mode-or-ids>","topology shorthand (gateway | direct | custom | none) OR comma-separated provider ids (e.g. openai,anthropic)").option("--deploy <target>","vercel | railway | cloudflare | selfhost").option("--docs <id>","fumadocs | mintlify | docusaurus | nextra | vitepress | none").option("--email <id>","resend | postmark | ses | aliyun-dm | tencent-ses | netease | none").option("--storage <id>","r2 | s3 | supabase-storage | aliyun-oss | tencent-cos | qiniu | none").option("--monitoring <id>","sentry | datadog | aliyun-arms | tingyun | none").option("--analytics <id>","posthog | plausible | umami | baidu | sensors | none").option("--sms <id>","twilio | aliyun-sms | tencent-sms | yunpian | none").option("--queue <id>","qstash | bullmq | sqs | none").option("--search <id>","meilisearch | typesense | algolia | pgvector | none").option("--cache <id>","upstash-redis | vercel-kv | redis | dragonfly | none").option("--notifications <id>","novu | knock | custom | none").option("--webhooks <id>","svix | custom | none").option("--cms <id>","sanity | contentful | strapi | none").option("--feature-flags <id>","vercel-flags | growthbook | configcat | none").option("--captcha <id>","turnstile | hcaptcha | aliyun-slide | none").option("--mcp <mode>","on | off (default: on)").option("--metering <mode>","auto | on | off (default: auto \u2014 auto-on when payment is set)").option("--billing-mode <mode>","usage | seat | credits (default: usage)").option("--idp <id>","clerk | oauth-server (default: clerk)").option("--access-gate <mode>","none | invite (default: none)").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: false \u2014 @nebutra/audit is WIP)").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("--with-workflows","scaffold workflows/ (inngest + n8n + pusher stubs)").option("--with-python-backend","scaffold backends/python/ (FastAPI stub \u2014 only when TS-by-Default ADR exception applies)").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}import kn from"picocolors";var Kt=[{id:"local",name:"Local / Self-hosted Docker",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres:postgres@localhost:5432/$PROJECT",comment:"Local Postgres via docker-compose (pnpm infra:up)"}],docs:"https://www.postgresql.org/docs/",description:"Docker on localhost. You operate it.",tier:"self-hosted"},{id:"supabase",name:"Supabase",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:5432/postgres?sslmode=require",comment:"Supabase session pooler \u2014 use for runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://postgres:<password>@db.<project-ref>.supabase.co:5432/postgres?sslmode=require",comment:"Supabase direct \u2014 use for Prisma migrations"},{name:"NEXT_PUBLIC_SUPABASE_URL",placeholder:"https://<project>.supabase.co"},{name:"NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY",placeholder:""},{name:"NEXT_PUBLIC_SUPABASE_ANON_KEY",placeholder:""},{name:"SUPABASE_PUBLISHABLE_KEY",placeholder:""},{name:"SUPABASE_SERVICE_ROLE_KEY",placeholder:""}],docs:"https://supabase.com/docs",description:"Managed Postgres + auth/storage/realtime/edge-functions.",tier:"managed"},{id:"neon",name:"Neon",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>-pooler.<region>.neon.tech/<db>?sslmode=require",comment:"Neon pooled \u2014 runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>.<region>.neon.tech/<db>?sslmode=require",comment:"Neon direct (no -pooler) \u2014 migrations"}],docs:"https://neon.tech/docs",description:"Serverless Postgres with branching and scale-to-zero.",tier:"managed"},{id:"vercel-postgres",name:"Vercel Postgres",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"$POSTGRES_PRISMA_URL",comment:"Vercel Marketplace injects POSTGRES_PRISMA_URL automatically"},{name:"DIRECT_URL",placeholder:"$POSTGRES_URL_NON_POOLING",comment:"Vercel Marketplace injects POSTGRES_URL_NON_POOLING automatically"}],docs:"https://vercel.com/docs/storage/vercel-postgres",description:"Neon-backed, auto-provisioned via Vercel Marketplace.",tier:"managed"},{id:"planetscale",name:"PlanetScale Postgres",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres.<branch-id>:<password>@<host>.horizon.psdb.cloud:6432/postgres?sslmode=require",comment:"PlanetScale Postgres pooled/PgBouncer URL \u2014 runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://postgres.<branch-id>:<password>@<host>.horizon.psdb.cloud:5432/postgres?sslmode=require",comment:"PlanetScale Postgres direct URL \u2014 Prisma migrations"}],docs:"https://planetscale.com/docs/postgres",description:"Managed Postgres with branching; compatible with Sailor migrations.",tier:"managed"},{id:"railway",name:"Railway",region:"global",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"$DATABASE_URL",comment:"Railway service env var; injected when you link a Postgres service"}],docs:"https://docs.railway.app/databases/postgresql",description:"Generalist managed infra; standard TCP Postgres/MySQL.",tier:"managed"},{id:"aliyun-rds",name:"Aliyun RDS",region:"cn",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@<rds-instance>.rds.aliyuncs.com:5432/<db>",comment:"Aliyun RDS Postgres \u2014 internal VPC endpoint recommended"}],docs:"https://www.alibabacloud.com/help/en/rds",description:"Aliyun RDS \u2014 China compliance + intranet routing.",tier:"managed"},{id:"tencent-cdb",name:"Tencent CloudDB (CDB)",region:"cn",supportedEngines:["mysql","postgresql"],envVars:[{name:"DATABASE_URL",placeholder:"mysql://<user>:<pwd>@<cdb-instance>.tencentcdb.com:3306/<db>",comment:"Tencent CloudDB \u2014 VPC endpoint recommended"}],docs:"https://intl.cloud.tencent.com/document/product/236",description:"Tencent CloudDB \u2014 China compliance.",tier:"managed"},{id:"none",name:"None",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[],docs:"",description:"Skip database scaffolding.",tier:"self-hosted"}];function st(e){return Kt.find(t=>t.id===e)}function xn(e){return e==="cn"||e==="hybrid"?"local":"supabase"}var it=[{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 $t(e){let t=e==="supabase"?"supabase-storage":e;return it.some(n=>n.id===t)?t:void 0}function Rn(e){let t=$t(e);return t?it.find(n=>n.id===t):void 0}var Qc=it.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Nn(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function Yt(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 qt(e,t,n){let o=e?.trim().toLowerCase()??xn(t),r=st(o);if(!r){let i=Kt.map(a=>a.id).join(", ");throw new Error(`Unknown --db-host="${o}". Valid: ${i}`)}let s=n;return r.forcedEngine&&s!=="none"&&s!==r.forcedEngine&&(s=r.forcedEngine),{hostId:r.id,engine:s}}function Gt(e){return e==="drizzle"?"drizzle":"prisma"}function Ht(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function Wt(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 Xt(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==="supabase"||t==="supabase-auth"?"supabase":t==="none"?"none":"clerk"}var Xr=new Set(["gateway","direct","custom","none"]);function zt(e){if(!e)return!1;let t=e.trim().toLowerCase();return Xr.has(t)}function Jt(e){if(!e)return["openai"];if(zt(e))return[];let t=e.split(",").map(n=>n.trim().toLowerCase());return t.includes("none")?[]:t}function On(e,t){let n=e??t;return $t(n)??n}var Tn={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function Qt(e,t){if(!e)return"fumadocs";let n=e.toLowerCase();if(n==="fumadocs"||n==="none")return n;if(n in Tn){let o=Tn[n];return t?process.stdout.write(JSON.stringify({event:"notice",kind:"docs-fallback",requested:n,effective:"fumadocs"})+`
3
3
  `):process.stdout.write(kn.yellow(`\u26A0 ${o} support is coming in v1.2. Falling back to fumadocs.
4
4
  `)+kn.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
5
- `)),"fumadocs"}return"fumadocs"}function Zt(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 en(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function Ln(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:"none",mcp:"on",metering:"auto",billingMode:"usage",idp:"clerk",accessGate:"none"}}function tn(e){return e==="cn"?"wechat":"stripe"}import*as Y from"@clack/prompts";import ir from"picocolors";var nn=[{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:[]}],np=nn.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var zs=["openai","anthropic","google"],Js=["openai"];function on(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let n=t.length>0?t:[...zs];return{mode:"gateway",providerIds:n,customEndpoint:e.customEndpoint,routing:{profile:"multi-provider-gateway",providerSeed:n,runtimeGovernance:!0}}}case"direct":{let n=t.length>0?t:[...Js];return{mode:"direct",providerIds:n,customEndpoint:e.customEndpoint,routing:{profile:"direct-adapters",providerSeed:n,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}}}}var He=[{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"}],Qs=new Set(He.map(e=>e.id));function Un(e){return He.find(t=>t.id===e)}function Mn(e){if(!e)return[];let t=e.split(",").map(s=>s.trim().toLowerCase()).filter(Boolean);if(t.includes("none"))return[];let n=[],o=new Set;for(let s of t)Qs.has(s)&&!o.has(s)&&(n.push(s),o.add(s));return n}import ee from"fs";import T from"path";import{fileURLToPath as Zs}from"url";var er=Zs(import.meta.url),Dn=T.dirname(er),tr={web:"vercel","landing-page":"vercel","design-docs":"vercel","sailor-docs":"vercel",gateway:"cloudflare-workers","python-ai":"ecs-docker"};function nr(){let e=[T.join(Dn,"..","templates","deploy"),T.join(Dn,"..","..","templates","deploy")];for(let t of e)if(ee.existsSync(t))return t;return e[0]}function jn(e){switch(e){case"cloudflare":return{web:"cloudflare-pages","landing-page":"cloudflare-pages","design-docs":"cloudflare-pages","sailor-docs":"cloudflare-pages",gateway:"cloudflare-workers","python-ai":"ecs-docker"};case"selfhost":return{web:"standalone","landing-page":"standalone","design-docs":"standalone","sailor-docs":"standalone",gateway:"ecs-docker","python-ai":"ecs-docker"};case"railway":return{web:"railway","landing-page":"railway","design-docs":"railway","sailor-docs":"railway",gateway:"railway","python-ai":"railway"};case"none":case"vercel":return{...tr}}}function or(e){return`DEPLOY_TARGET_${e.toUpperCase().replace(/-/g,"_")}`}async function Fn(e,t){let n=T.join(e,"backends","gateway");ee.existsSync(n)&&await ee.promises.copyFile(T.join(t,"wrangler.gateway.toml"),T.join(n,"wrangler.toml"))}async function Bn(e,t){let n=T.join(e,".env.example"),o;try{o=await ee.promises.readFile(n,"utf8")}catch(i){if(i.code==="ENOENT")return;throw i}if(o.includes("# Deployment Targets"))return;let r=["","# Deployment Targets",...Object.entries(t).map(([i,a])=>`${or(i)}="${a}"`)].join(`
6
- `);await ee.promises.appendFile(n,`${r}
7
- `)}async function Vn(e,t){if(t==="none")return;let n=nr();t==="vercel"?(await ee.promises.copyFile(T.join(n,"vercel.json"),T.join(e,"vercel.json")),await Fn(e,n)):t==="railway"?await ee.promises.copyFile(T.join(n,"railway.toml"),T.join(e,"railway.toml")):t==="cloudflare"?(await ee.promises.copyFile(T.join(n,"wrangler.toml"),T.join(e,"wrangler.toml")),await Fn(e,n)):t==="selfhost"&&(await ee.promises.copyFile(T.join(n,"docker-compose.yml"),T.join(e,"docker-compose.yml")),await ee.promises.copyFile(T.join(n,"Dockerfile.web"),T.join(e,"Dockerfile.web")))}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",invite:"foundation"};function rr(e){return e?sr[e]??"stable":"stable"}function We(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function he(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 Kn(e){let t=[];for(let{flag:n,provider:o}of e){if(!o||o==="none")continue;let s=rr(o);s!=="stable"&&t.push({flag:n,provider:o,status:s})}return t}function Ee(e,t){if(e===void 0)return t;let n=String(e).trim().toLowerCase();return n==="true"||n==="1"||n==="yes"||n==="on"?!0:n==="false"||n==="0"||n==="no"||n==="off"?!1:t}function $n(e,t){let n=t==="cn";return{cronJobs:Ee(e.cronJobs,!0),auditLog:Ee(e.auditLog,!1),apiKeys:Ee(e.apiKeys,!0),webhooks:Ee(e.webhooks,!0),commandPalette:Ee(e.commandPalette,!0),cookieConsent:Ee(e.cookieConsent,!0),legalPages:Ee(e.legalPages,!0),chinaCompliance:Ee(e.chinaCompliance,n)}}async function ar(e,t,n,o){let s={};return t||(s.region=()=>Y.select({message:"Target region?",options:[{value:"global",label:"global \u2014 \u6D77\u5916\u4F18\u5148"},{value:"cn",label:"cn \u2014 \u56FD\u5185\u4F18\u5148"},{value:"hybrid",label:"hybrid \u2014 \u53CC\u8F68\uFF08\u56FD\u5185+\u51FA\u6D77\uFF09"}],initialValue:"global"})),n||(s.auth=()=>Y.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:"supabase",label:"Supabase Auth",hint:"managed auth with Supabase storage/realtime ecosystem"},{value:"none",label:"None"}],initialValue:"clerk"})),o||(s.aiMode=()=>Y.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"}),s.aiProviders=({results:r})=>{if(r.aiMode!=="direct")return Promise.resolve([]);let i=nn.map(a=>({value:a.id,label:`[${a.category}] ${a.name}`}));return Y.multiselect({message:"Select direct AI provider adapters (expert path)",options:i,initialValues:["openai"],required:!1})},s.customAiName=({results:r})=>r.aiMode==="custom"?Y.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),s.customAiBaseUrl=({results:r})=>r.aiMode==="custom"?Y.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:i=>{if(!i?.length)return"Base URL is required."}}):Promise.resolve(void 0),s.customAiApiKeyEnv=({results:r})=>r.aiMode==="custom"?Y.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0)),Object.keys(s).length===0?{}:await Y.group(s,{onCancel:()=>{process.stdout.write(ir.red(`\u2718 Cancelled
8
- `)),process.exit(130)}})}async function Yn(e,t){let n=!!e.region,o=!!e.auth,s=!!e.payment,r=!!e.ai,i=!!e.email,a=!!e.storage,c=!!e.monitoring,l=!!e.analytics,u=!!e.sms,d=e.i18n!==void 0,h=!!e.yes||!process.stdin.isTTY,f,E,S,m,P,G,M,ge=Mn(e.socialLogin),pe,Z,j,K,C,H,le;if(h){f=en(e.region),E=Gt(e.orm);{let $=Yt(e.db),ft=qt(e.dbHost,f,$);S=ft.engine,m=ft.hostId}let W=s?e.payment:tn(f);P=Ht(W),G=Wt(W),M=Xt(e.auth);let Ge="gateway";if(r){let $=e.ai?.trim().toLowerCase()??"";zt($)?Ge=$:Ge="direct"}let ot=on({mode:Ge,providerIds:r?Jt(e.ai):void 0});pe=ot.mode,Z=ot.routing,j=ot.providerIds,C=Zt(e.deploy),H=Qt(e.docs,t),le=d?!!e.i18n:!0}else{let W=await ar(e,n,o,r);f=en(n?e.region:W.region),E=Gt(e.orm);{let ft=Yt(e.db),An=qt(e.dbHost,f,ft);S=An.engine,m=An.hostId}let Ge=s?e.payment:tn(f);P=Ht(Ge),G=Wt(Ge),M=Xt(o?e.auth:W.auth);let ot=W.aiMode==="custom"?{name:W.customAiName??"custom",baseURL:W.customAiBaseUrl??"",apiKeyEnvName:W.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,$=on({mode:r?e.ai?.trim().toLowerCase()==="none"?"none":"direct":W.aiMode??"gateway",providerIds:r?Jt(e.ai):W.aiProviders,customEndpoint:ot});pe=$.mode,Z=$.routing,j=$.providerIds,$.customEndpoint&&(K={name:$.customEndpoint.name,baseURL:$.customEndpoint.baseURL,apiKeyEnvName:$.customEndpoint.apiKeyEnvName}),C=Zt(e.deploy),H=Qt(e.docs,t),le=d?!!e.i18n:!0}let w=Ln(f),fe=i?e.email:w.email,Ye=On(a?e.storage:void 0,w.storage),qe=c?e.monitoring:w.monitoring,ye=l?e.analytics:w.analytics,v=u?e.sms:w.sms,k=e.queue??w.queue,I=e.search??w.search,x=e.cache??w.cache,Mt=e.notifications??w.notifications,Dt=e.webhooks??w.webhooks,En=e.cms??w.cms,Ft=e.featureFlags??w.featureFlags,jt=e.captcha??w.captcha,vn=e.mcp??w.mcp,bn=e.metering??w.metering,_n=e.billingMode??w.billingMode,Pn=e.idp??w.idp,Bt=e.accessGate==="invite"?"invite":w.accessGate,wn=jn(C),Se=$n({cronJobs:e.cronJobs,auditLog:e.auditLog,apiKeys:e.apiKeys,commandPalette:e.commandPalette,cookieConsent:e.cookieConsent,legalPages:e.legalPages,chinaCompliance:e.chinaCompliance},f),$s=Kn([{flag:"queue",provider:k},{flag:"search",provider:I},{flag:"notifications",provider:Mt},{flag:"webhooks",provider:Dt},{flag:"feature-flags",provider:Ft},{flag:"captcha",provider:jt},{flag:"access-gate",provider:Bt}]),Ys={region:f,orm:E,database:S,payment:P,aiMode:pe,aiRouting:Z,aiProviders:j,customAiEndpoint:K,deployTarget:C,deployTargets:wn,docs:H,i18n:le,email:fe,storage:Ye,monitoring:qe,analytics:ye,sms:v,queue:k,search:I,cache:x,notifications:Mt,webhooks:Dt,cms:En,featureFlags:Ft,captcha:jt,mcp:vn,metering:bn,billingMode:_n,idp:Pn,accessGate:Bt,cronJobs:Se.cronJobs,auditLog:Se.auditLog,apiKeys:Se.apiKeys,commandPalette:Se.commandPalette,cookieConsent:Se.cookieConsent,legalPages:Se.legalPages,chinaCompliance:Se.chinaCompliance};return{region:f,orm:E,database:S,databaseHost:m,payment:P,paymentChoice:G,auth:M,socialLoginIds:ge,aiMode:pe,aiRouting:Z,aiProviders:j,customAiEndpoint:K,deployTarget:C,deployTargets:wn,docs:H,i18n:le,email:fe,storage:Ye,monitoring:qe,analytics:ye,sms:v,queue:k,search:I,cache:x,notifications:Mt,webhooks:Dt,cms:En,featureFlags:Ft,captcha:jt,mcp:vn,metering:bn,billingMode:_n,idp:Pn,accessGate:Bt,waveToggles:Se,previewSelections:$s,config:Ys}}import{execFileSync as Ot}from"child_process";import Lt from"fs";import Ke from"path";import mt from"picocolors";import xc from"update-notifier";import A from"picocolors";function cr(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function qn(e){let t=cr(),n=t?"\u2693":"-",o=t?"\u25B8":"->",s=t?"\u2605":"*",r=t?"\u{1F4E7}":"*",a=["",` ${t?A.bold(`${n} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`):`${n} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`}`,"",` ${t?A.bold("Next:"):"Next:"}`,` ${o} cd ${e.targetDir}`];e.skippedInstall&&a.push(` ${o} pnpm install (if --no-install was set)`),a.push(` ${o} fill in .env.local ${t?A.dim("\u2192 add provider keys before booting apps"):"-> add provider keys before booting apps"}`,` ${o} pnpm db:migrate ${t?A.dim("\u2192 sync Prisma schema"):"-> sync Prisma schema"}`,` ${o} pnpm db:seed ${t?A.dim("\u2192 load example tenants and records"):"-> load example tenants and records"}`,` ${o} pnpm dev ${t?A.dim("\u2192 http://localhost:3000"):"-> http://localhost:3000"}`,"",` ${t?A.bold("Customize:"):"Customize:"}`,` ${o} pnpm brand:init ${t?A.dim("\u2192 create brand.config.ts"):"-> create brand.config.ts"}`,` ${o} pnpm brand:apply ${t?A.dim("\u2192 propagate brand changes"):"-> propagate brand changes"}`,` ${o} pnpm preset:env ${t?A.dim("\u2192 review preset env requirements"):"-> review preset env requirements"}`,"",` ${t?A.bold("Useful scripts:"):"Useful scripts:"}`,` ${o} pnpm infra:up ${t?A.dim("\u2192 start local PostgreSQL/Redis/ClickHouse"):"-> start local PostgreSQL/Redis/ClickHouse"}`,` ${o} pnpm generate:api-types ${t?A.dim("\u2192 refresh shared API client types"):"-> refresh shared API client types"}`,` ${o} pnpm lint ${t?A.dim("\u2192 quick repo sanity check"):"-> quick repo sanity check"}`,` ${o} pnpm audit ${t?A.dim("\u2192 scan deps for known CVEs"):"-> scan deps for known CVEs"}`);let c=e.previewSelections??[];if(c.length>0){let _=t?A.bold(A.yellow("\u26A0 Preview features selected:")):"!! Preview features selected:";a.push("",` ${_}`);for(let h of c){let f=We(h.status),E=` ${o} ${h.flag} (${h.provider}) ${f}`;a.push(t?A.yellow(E):E)}a.push("",` ${t?A.dim(he("foundation")):he("foundation")}`,` ${t?A.dim("You may need to contribute the provider integration yourself."):"You may need to contribute the provider integration yourself."}`,` ${t?A.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??{},u=_=>_!==!1,d=[];u(l.apiKeys)&&d.push("Manage API keys at /settings/api-keys"),u(l.auditLog)&&d.push("View audit log at /settings/audit-log"),d.push("Configure webhooks at /settings/webhooks"),u(l.commandPalette)&&d.push("Press Cmd/Ctrl+K to open the command palette"),d.push("Edit notification preferences at /settings/notifications"),d.push("Export your data at /settings/account/export"),l.chinaCompliance&&d.push("China deployments \u2014 see packages/ops/china-compliance/README.md"),a.push("",` ${t?A.bold("What you can do next:"):"What you can do next:"}`);for(let _ of d)a.push(` ${o} ${_}`);a.push("",` ${t?A.bold("Ship faster:"):"Ship faster:"}`,` ${s} Star us https://github.com/nebutra/nebutra-sailor`,` ${r} Free license https://nebutra.com/get-license`,""),process.stdout.write(a.join(`
5
+ `)),"fumadocs"}return"fumadocs"}function Zt(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 en(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function Ln(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:"none",mcp:"on",metering:"auto",billingMode:"usage",idp:"clerk",accessGate:"none"}}function tn(e){return e==="cn"?"wechat":"stripe"}import*as Y from"@clack/prompts";import is from"picocolors";var nn=[{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:[]}],rp=nn.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var zr=["openai","anthropic","google"],Jr=["openai"];function on(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let n=t.length>0?t:[...zr];return{mode:"gateway",providerIds:n,customEndpoint:e.customEndpoint,routing:{profile:"multi-provider-gateway",providerSeed:n,runtimeGovernance:!0}}}case"direct":{let n=t.length>0?t:[...Jr];return{mode:"direct",providerIds:n,customEndpoint:e.customEndpoint,routing:{profile:"direct-adapters",providerSeed:n,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}}}}var We=[{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"}],Qr=new Set(We.map(e=>e.id));function Un(e){return We.find(t=>t.id===e)}function Mn(e){if(!e)return[];let t=e.split(",").map(r=>r.trim().toLowerCase()).filter(Boolean);if(t.includes("none"))return[];let n=[],o=new Set;for(let r of t)Qr.has(r)&&!o.has(r)&&(n.push(r),o.add(r));return n}import ee from"fs";import T from"path";import{fileURLToPath as Zr}from"url";var es=Zr(import.meta.url),Dn=T.dirname(es),ts={web:"vercel","landing-page":"vercel","design-docs":"vercel","sailor-docs":"vercel",gateway:"cloudflare-workers","python-ai":"ecs-docker"};function ns(){let e=[T.join(Dn,"..","templates","deploy"),T.join(Dn,"..","..","templates","deploy")];for(let t of e)if(ee.existsSync(t))return t;return e[0]}function jn(e){switch(e){case"cloudflare":return{web:"cloudflare-pages","landing-page":"cloudflare-pages","design-docs":"cloudflare-pages","sailor-docs":"cloudflare-pages",gateway:"cloudflare-workers","python-ai":"ecs-docker"};case"selfhost":return{web:"standalone","landing-page":"standalone","design-docs":"standalone","sailor-docs":"standalone",gateway:"ecs-docker","python-ai":"ecs-docker"};case"railway":return{web:"railway","landing-page":"railway","design-docs":"railway","sailor-docs":"railway",gateway:"railway","python-ai":"railway"};case"none":case"vercel":return{...ts}}}function os(e){return`DEPLOY_TARGET_${e.toUpperCase().replace(/-/g,"_")}`}async function Fn(e,t){let n=T.join(e,"backends","gateway");ee.existsSync(n)&&await ee.promises.copyFile(T.join(t,"wrangler.gateway.toml"),T.join(n,"wrangler.toml"))}async function Bn(e,t){let n=T.join(e,".env.example"),o;try{o=await ee.promises.readFile(n,"utf8")}catch(i){if(i.code==="ENOENT")return;throw i}if(o.includes("# Deployment Targets"))return;let s=["","# Deployment Targets",...Object.entries(t).map(([i,a])=>`${os(i)}="${a}"`)].join(`
6
+ `);await ee.promises.appendFile(n,`${s}
7
+ `)}async function Vn(e,t){if(t==="none")return;let n=ns();t==="vercel"?(await ee.promises.copyFile(T.join(n,"vercel.json"),T.join(e,"vercel.json")),await Fn(e,n)):t==="railway"?await ee.promises.copyFile(T.join(n,"railway.toml"),T.join(e,"railway.toml")):t==="cloudflare"?(await ee.promises.copyFile(T.join(n,"wrangler.toml"),T.join(e,"wrangler.toml")),await Fn(e,n)):t==="selfhost"&&(await ee.promises.copyFile(T.join(n,"docker-compose.yml"),T.join(e,"docker-compose.yml")),await ee.promises.copyFile(T.join(n,"Dockerfile.web"),T.join(e,"Dockerfile.web")))}var rs={qstash:"foundation",bullmq:"foundation",upstash:"foundation",sqs:"foundation",meilisearch:"foundation",typesense:"foundation",algolia:"foundation",pgvector:"foundation","vercel-flags":"foundation",growthbook:"foundation",configcat:"foundation",turnstile:"wip",hcaptcha:"wip","aliyun-slide":"wip",invite:"foundation"};function ss(e){return e?rs[e]??"stable":"stable"}function Xe(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function he(e){switch(e){case"stable":return"Production-ready.";case"foundation":return"Foundation status \u2014 core contracts work, but production use still requires provider credentials, adapter wiring, or a verified integration contract.";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 Kn(e){let t=[];for(let{flag:n,provider:o}of e){if(!o||o==="none")continue;let r=ss(o);r!=="stable"&&t.push({flag:n,provider:o,status:r})}return t}function Ee(e,t){if(e===void 0)return t;let n=String(e).trim().toLowerCase();return n==="true"||n==="1"||n==="yes"||n==="on"?!0:n==="false"||n==="0"||n==="no"||n==="off"?!1:t}function $n(e,t){let n=t==="cn";return{cronJobs:Ee(e.cronJobs,!0),auditLog:Ee(e.auditLog,!1),apiKeys:Ee(e.apiKeys,!0),webhooks:Ee(e.webhooks,!0),commandPalette:Ee(e.commandPalette,!0),cookieConsent:Ee(e.cookieConsent,!0),legalPages:Ee(e.legalPages,!0),chinaCompliance:Ee(e.chinaCompliance,n)}}async function as(e,t,n,o){let r={};return t||(r.region=()=>Y.select({message:"Target region?",options:[{value:"global",label:"global \u2014 \u6D77\u5916\u4F18\u5148"},{value:"cn",label:"cn \u2014 \u56FD\u5185\u4F18\u5148"},{value:"hybrid",label:"hybrid \u2014 \u53CC\u8F68\uFF08\u56FD\u5185+\u51FA\u6D77\uFF09"}],initialValue:"global"})),n||(r.auth=()=>Y.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:"supabase",label:"Supabase Auth",hint:"managed auth with Supabase storage/realtime ecosystem"},{value:"none",label:"None"}],initialValue:"clerk"})),o||(r.aiMode=()=>Y.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"}),r.aiProviders=({results:s})=>{if(s.aiMode!=="direct")return Promise.resolve([]);let i=nn.map(a=>({value:a.id,label:`[${a.category}] ${a.name}`}));return Y.multiselect({message:"Select direct AI provider adapters (expert path)",options:i,initialValues:["openai"],required:!1})},r.customAiName=({results:s})=>s.aiMode==="custom"?Y.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),r.customAiBaseUrl=({results:s})=>s.aiMode==="custom"?Y.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:i=>{if(!i?.length)return"Base URL is required."}}):Promise.resolve(void 0),r.customAiApiKeyEnv=({results:s})=>s.aiMode==="custom"?Y.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0)),Object.keys(r).length===0?{}:await Y.group(r,{onCancel:()=>{process.stdout.write(is.red(`\u2718 Cancelled
8
+ `)),process.exit(130)}})}async function Yn(e,t){let n=!!e.region,o=!!e.auth,r=!!e.payment,s=!!e.ai,i=!!e.email,a=!!e.storage,c=!!e.monitoring,p=!!e.analytics,u=!!e.sms,d=e.i18n!==void 0,h=!!e.yes||!process.stdin.isTTY,f,E,S,m,P,G,M,ge=Mn(e.socialLogin),pe,Z,j,K,C,H,le;if(h){f=en(e.region),E=Gt(e.orm);{let $=Yt(e.db),yt=qt(e.dbHost,f,$);S=yt.engine,m=yt.hostId}let W=r?e.payment:tn(f);P=Ht(W),G=Wt(W),M=Xt(e.auth);let He="gateway";if(s){let $=e.ai?.trim().toLowerCase()??"";zt($)?He=$:He="direct"}let rt=on({mode:He,providerIds:s?Jt(e.ai):void 0});pe=rt.mode,Z=rt.routing,j=rt.providerIds,C=Zt(e.deploy),H=Qt(e.docs,t),le=d?!!e.i18n:!0}else{let W=await as(e,n,o,s);f=en(n?e.region:W.region),E=Gt(e.orm);{let yt=Yt(e.db),An=qt(e.dbHost,f,yt);S=An.engine,m=An.hostId}let He=r?e.payment:tn(f);P=Ht(He),G=Wt(He),M=Xt(o?e.auth:W.auth);let rt=W.aiMode==="custom"?{name:W.customAiName??"custom",baseURL:W.customAiBaseUrl??"",apiKeyEnvName:W.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,$=on({mode:s?e.ai?.trim().toLowerCase()==="none"?"none":"direct":W.aiMode??"gateway",providerIds:s?Jt(e.ai):W.aiProviders,customEndpoint:rt});pe=$.mode,Z=$.routing,j=$.providerIds,$.customEndpoint&&(K={name:$.customEndpoint.name,baseURL:$.customEndpoint.baseURL,apiKeyEnvName:$.customEndpoint.apiKeyEnvName}),C=Zt(e.deploy),H=Qt(e.docs,t),le=d?!!e.i18n:!0}let w=Ln(f),fe=i?e.email:w.email,qe=On(a?e.storage:void 0,w.storage),Ge=c?e.monitoring:w.monitoring,ye=p?e.analytics:w.analytics,v=u?e.sms:w.sms,k=e.queue??w.queue,I=e.search??w.search,x=e.cache??w.cache,Mt=e.notifications??w.notifications,Dt=e.webhooks??w.webhooks,En=e.cms??w.cms,Ft=e.featureFlags??w.featureFlags,jt=e.captcha??w.captcha,vn=e.mcp??w.mcp,bn=e.metering??w.metering,_n=e.billingMode??w.billingMode,Pn=e.idp??w.idp,Bt=e.accessGate==="invite"?"invite":w.accessGate,wn=jn(C),Se=$n({cronJobs:e.cronJobs,auditLog:e.auditLog,apiKeys:e.apiKeys,commandPalette:e.commandPalette,cookieConsent:e.cookieConsent,legalPages:e.legalPages,chinaCompliance:e.chinaCompliance},f),$r=Kn([{flag:"queue",provider:k},{flag:"search",provider:I},{flag:"notifications",provider:Mt},{flag:"webhooks",provider:Dt},{flag:"feature-flags",provider:Ft},{flag:"captcha",provider:jt},{flag:"access-gate",provider:Bt}]),Yr={region:f,orm:E,database:S,databaseHost:m,payment:P,aiMode:pe,aiRouting:Z,aiProviders:j,customAiEndpoint:K,deployTarget:C,deployTargets:wn,docs:H,i18n:le,email:fe,storage:qe,monitoring:Ge,analytics:ye,sms:v,queue:k,search:I,cache:x,notifications:Mt,webhooks:Dt,cms:En,featureFlags:Ft,captcha:jt,mcp:vn,metering:bn,billingMode:_n,idp:Pn,accessGate:Bt,cronJobs:Se.cronJobs,auditLog:Se.auditLog,apiKeys:Se.apiKeys,commandPalette:Se.commandPalette,cookieConsent:Se.cookieConsent,legalPages:Se.legalPages,chinaCompliance:Se.chinaCompliance};return{region:f,orm:E,database:S,databaseHost:m,payment:P,paymentChoice:G,auth:M,socialLoginIds:ge,aiMode:pe,aiRouting:Z,aiProviders:j,customAiEndpoint:K,deployTarget:C,deployTargets:wn,docs:H,i18n:le,email:fe,storage:qe,monitoring:Ge,analytics:ye,sms:v,queue:k,search:I,cache:x,notifications:Mt,webhooks:Dt,cms:En,featureFlags:Ft,captcha:jt,mcp:vn,metering:bn,billingMode:_n,idp:Pn,accessGate:Bt,waveToggles:Se,previewSelections:$r,config:Yr}}import{execFileSync as Ot}from"child_process";import Lt from"fs";import $e from"path";import gt from"picocolors";import kc from"update-notifier";import A from"picocolors";function cs(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function qn(e){let t=cs(),n=t?"\u2693":"-",o=t?"\u25B8":"->",r=t?"\u2605":"*",s=t?"\u{1F4E7}":"*",a=["",` ${t?A.bold(`${n} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`):`${n} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`}`,"",` ${t?A.bold("Next:"):"Next:"}`,` ${o} cd ${e.targetDir}`];e.skippedInstall&&a.push(` ${o} pnpm install (if --no-install was set)`),a.push(` ${o} fill in .env.local ${t?A.dim("\u2192 add provider keys before booting apps"):"-> add provider keys before booting apps"}`,` ${o} pnpm db:migrate ${t?A.dim("\u2192 sync Prisma schema"):"-> sync Prisma schema"}`,` ${o} pnpm db:seed ${t?A.dim("\u2192 load example tenants and records"):"-> load example tenants and records"}`,` ${o} pnpm dev ${t?A.dim("\u2192 http://localhost:3000"):"-> http://localhost:3000"}`,"",` ${t?A.bold("Customize:"):"Customize:"}`,` ${o} pnpm brand:init ${t?A.dim("\u2192 create brand.config.ts"):"-> create brand.config.ts"}`,` ${o} pnpm brand:apply ${t?A.dim("\u2192 propagate brand changes"):"-> propagate brand changes"}`,` ${o} pnpm preset:env ${t?A.dim("\u2192 review preset env requirements"):"-> review preset env requirements"}`,"",` ${t?A.bold("Useful scripts:"):"Useful scripts:"}`,` ${o} pnpm infra:up ${t?A.dim("\u2192 start local PostgreSQL/Redis/ClickHouse"):"-> start local PostgreSQL/Redis/ClickHouse"}`,` ${o} pnpm generate:api-types ${t?A.dim("\u2192 refresh shared API client types"):"-> refresh shared API client types"}`,` ${o} pnpm lint ${t?A.dim("\u2192 quick repo sanity check"):"-> quick repo sanity check"}`,` ${o} pnpm audit ${t?A.dim("\u2192 scan deps for known CVEs"):"-> scan deps for known CVEs"}`);let c=e.previewSelections??[];if(c.length>0){let _=t?A.bold(A.yellow("\u26A0 Preview features selected:")):"!! Preview features selected:";a.push("",` ${_}`);for(let h of c){let f=Xe(h.status),E=` ${o} ${h.flag} (${h.provider}) ${f}`;a.push(t?A.yellow(E):E)}a.push("",` ${t?A.dim(he("foundation")):he("foundation")}`,` ${t?A.dim("You may need to contribute the provider integration yourself."):"You may need to contribute the provider integration yourself."}`,` ${t?A.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 p=e.waveFeatures??{},u=_=>_!==!1,d=[];u(p.apiKeys)&&d.push("Manage API keys at /settings/api-keys"),u(p.auditLog)&&d.push("View audit log at /settings/audit-log"),d.push("Configure webhooks at /settings/webhooks"),u(p.commandPalette)&&d.push("Press Cmd/Ctrl+K to open the command palette"),d.push("Edit notification preferences at /settings/notifications"),d.push("Export your data at /settings/account/export"),p.chinaCompliance&&d.push("China deployments \u2014 see packages/ops/china-compliance/README.md"),a.push("",` ${t?A.bold("What you can do next:"):"What you can do next:"}`);for(let _ of d)a.push(` ${o} ${_}`);a.push("",` ${t?A.bold("Ship faster:"):"Ship faster:"}`,` ${r} Star us https://github.com/nebutra/nebutra-sailor`,` ${s} Free license https://nebutra.com/get-license`,""),process.stdout.write(a.join(`
9
9
  `)+`
10
- `)}import Xe from"fs";import B from"path";var Gn=[{id:"posthog",name:"PostHog",region:"both",envVars:["POSTHOG_KEY","POSTHOG_HOST","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:""}],Ap=Gn.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Hn(e){return Gn.find(t=>t.id===e)}function pr(e){Xe.mkdirSync(e,{recursive:!0})}function te(e,t){pr(B.dirname(e)),Xe.writeFileSync(e,t)}function Ae(e,t){let n=B.join(e,".env.example");Xe.existsSync(n)?Xe.appendFileSync(n,`
11
- `+t):Xe.writeFileSync(n,t)}function lr(e){let t=`"use client";
10
+ `)}import ze from"fs";import B from"path";var Gn=[{id:"posthog",name:"PostHog",region:"both",envVars:["POSTHOG_KEY","POSTHOG_HOST","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:""}],Cp=Gn.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Hn(e){return Gn.find(t=>t.id===e)}function ps(e){ze.mkdirSync(e,{recursive:!0})}function te(e,t){ps(B.dirname(e)),ze.writeFileSync(e,t)}function Ie(e,t){let n=B.join(e,".env.example");ze.existsSync(n)?ze.appendFileSync(n,`
11
+ `+t):ze.writeFileSync(n,t)}function ls(e){let t=`"use client";
12
12
  /**
13
13
  * PostHog browser SDK \u2014 lazy-initialized on first access.
14
14
  */
@@ -91,12 +91,12 @@ export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
91
91
 
92
92
  return <>{children}</>;
93
93
  }
94
- `;te(B.join(e,"src","lib","analytics","posthog.client.ts"),t),te(B.join(e,"src","lib","analytics","posthog.server.ts"),n),te(B.join(e,"src","components","analytics","AnalyticsProvider.tsx"),o)}function dr(){return`# PostHog \u2014 product analytics
94
+ `;te(B.join(e,"src","lib","analytics","posthog.client.ts"),t),te(B.join(e,"src","lib","analytics","posthog.server.ts"),n),te(B.join(e,"src","components","analytics","AnalyticsProvider.tsx"),o)}function ds(){return`# PostHog \u2014 product analytics
95
95
  POSTHOG_KEY=
96
96
  POSTHOG_HOST=https://us.i.posthog.com
97
97
  NEXT_PUBLIC_POSTHOG_KEY=
98
98
  NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
99
- `}function ur(e){te(B.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
99
+ `}function us(e){te(B.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
100
100
  /**
101
101
  * Plausible script tag \u2014 lightweight, privacy-friendly analytics.
102
102
  */
@@ -116,10 +116,10 @@ export function PlausibleScript() {
116
116
  />
117
117
  );
118
118
  }
119
- `)}function mr(){return`# Plausible \u2014 privacy-friendly analytics
119
+ `)}function ms(){return`# Plausible \u2014 privacy-friendly analytics
120
120
  NEXT_PUBLIC_PLAUSIBLE_DOMAIN=
121
121
  NEXT_PUBLIC_PLAUSIBLE_SRC=https://plausible.io/js/script.js
122
- `}function gr(e){te(B.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
122
+ `}function gs(e){te(B.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
123
123
  /**
124
124
  * Umami analytics \u2014 self-hosted OR umami.is cloud.
125
125
  */
@@ -139,10 +139,10 @@ export function UmamiScript() {
139
139
  />
140
140
  );
141
141
  }
142
- `)}function fr(){return`# Umami \u2014 self-hostable analytics
142
+ `)}function fs(){return`# Umami \u2014 self-hostable analytics
143
143
  NEXT_PUBLIC_UMAMI_WEBSITE_ID=
144
144
  NEXT_PUBLIC_UMAMI_SRC=https://cloud.umami.is/script.js
145
- `}function yr(e){let t=`"use client";
145
+ `}function ys(e){let t=`"use client";
146
146
  import mixpanel from "mixpanel-browser";
147
147
 
148
148
  let initialized = false;
@@ -181,10 +181,10 @@ export function trackServer(
181
181
  if (!c) return;
182
182
  c.track(event, { distinct_id: distinctId, ...properties });
183
183
  }
184
- `;te(B.join(e,"src","lib","analytics","mixpanel.client.ts"),t),te(B.join(e,"src","lib","analytics","mixpanel.server.ts"),n)}function Sr(){return`# Mixpanel \u2014 product analytics
184
+ `;te(B.join(e,"src","lib","analytics","mixpanel.client.ts"),t),te(B.join(e,"src","lib","analytics","mixpanel.server.ts"),n)}function Ss(){return`# Mixpanel \u2014 product analytics
185
185
  MIXPANEL_TOKEN=
186
186
  NEXT_PUBLIC_MIXPANEL_TOKEN=
187
- `}function hr(e){te(B.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
187
+ `}function hs(e){te(B.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
188
188
  /**
189
189
  * \u767E\u5EA6\u7EDF\u8BA1 Baidu Tongji \u2014 hm.js \u57CB\u70B9\u811A\u672C.
190
190
  */
@@ -210,9 +210,9 @@ var _hmt = _hmt || [];
210
210
  />
211
211
  );
212
212
  }
213
- `)}function Er(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
213
+ `)}function Es(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
214
214
  NEXT_PUBLIC_BAIDU_STATS_ID=
215
- `}function vr(e){te(B.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
215
+ `}function vs(e){te(B.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
216
216
  /**
217
217
  * \u795E\u7B56\u5206\u6790 (Sensors Analytics) \u2014 sa-sdk-javascript \u5C01\u88C5.
218
218
  */
@@ -240,10 +240,10 @@ export function initSensors(): void {
240
240
  }
241
241
 
242
242
  export { sensors };
243
- `)}function br(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
243
+ `)}function bs(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
244
244
  NEXT_PUBLIC_SENSORS_SERVER_URL=
245
245
  NEXT_PUBLIC_SENSORS_APP_JS_URL=
246
- `}function _r(e){te(B.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
246
+ `}function _s(e){te(B.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
247
247
  /**
248
248
  * GrowingIO CDP \u2014 inline snippet installer.
249
249
  */
@@ -268,21 +268,21 @@ gdp("send");
268
268
  />
269
269
  );
270
270
  }
271
- `)}function Pr(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
271
+ `)}function Ps(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
272
272
  NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID=
273
- `}async function Wn(e,t,n="global"){let o=Hn(t);if(!o||o.id==="none")return;let s=B.join(e,"apps","web");if(!Xe.existsSync(s))return;let r=o.id;try{switch(r){case"posthog":lr(s),Ae(e,dr());return;case"plausible":ur(s),Ae(e,mr());return;case"umami":gr(s),Ae(e,fr());return;case"mixpanel":yr(s),Ae(e,Sr());return;case"baidu":hr(s),Ae(e,Er());return;case"sensors":vr(s),Ae(e,br());return;case"growingio":_r(s),Ae(e,Pr());return;default:return}}catch(i){throw console.error(`Failed to apply analytics selection "${t}":`,i),new Error(`Analytics scaffold for "${t}" failed \u2014 see stderr for details.`)}}var wr="https://analytics.nebutra.com";function Ar(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function Xn(e,t={}){Ar(t)||(async()=>{try{let n=await import("./dist-V6L2DNL2.js");if(typeof n.createProductAnalyticsClient!="function")return;let o=n.createProductAnalyticsClient({posthog:{apiKey:process.env.POSTHOG_KEY??process.env.NEXT_PUBLIC_POSTHOG_KEY??process.env.NEBUTRA_POSTHOG_KEY??"",host:process.env.POSTHOG_HOST??process.env.NEXT_PUBLIC_POSTHOG_HOST??process.env.NEBUTRA_POSTHOG_HOST??wr},onError:()=>{}});if(typeof o?.track!="function")return;let s=o.track("scaffold.completed",e);s&&typeof s.then=="function"&&await s.catch(()=>{})}catch{}})()}import q from"fs";import N from"path";function V(e){q.existsSync(e)&&q.rmSync(e,{recursive:!0,force:!0})}function yt(e,t){let n=N.join(e,".env.example");q.existsSync(n)?q.appendFileSync(n,`
274
- `+t):q.writeFileSync(n,t)}function St(e,t){if(!q.existsSync(e))return;let n=q.readFileSync(e,"utf8"),o=n.replace(/export type AuthProviderId\s*=\s*(?:"[^"]+"\s*\|\s*)+"[^"]+";/,`export type AuthProviderId = "${t}";`);o!==n&&q.writeFileSync(e,o)}function Ir(e,t){let n=N.join(e,"README.md");if(!q.existsSync(n)){q.writeFileSync(n,t);return}q.appendFileSync(n,`
275
- `+t)}async function zn(e,t){let n=N.join(e,"packages","iam","auth");if(!q.existsSync(n))return;if(t==="none"){V(n),Ir(e,`
273
+ `}async function Wn(e,t,n="global"){let o=Hn(t);if(!o||o.id==="none")return;let r=B.join(e,"apps","web");if(!ze.existsSync(r))return;let s=o.id;try{switch(s){case"posthog":ls(r),Ie(e,ds());return;case"plausible":us(r),Ie(e,ms());return;case"umami":gs(r),Ie(e,fs());return;case"mixpanel":ys(r),Ie(e,Ss());return;case"baidu":hs(r),Ie(e,Es());return;case"sensors":vs(r),Ie(e,bs());return;case"growingio":_s(r),Ie(e,Ps());return;default:return}}catch(i){throw console.error(`Failed to apply analytics selection "${t}":`,i),new Error(`Analytics scaffold for "${t}" failed \u2014 see stderr for details.`)}}var ws="https://analytics.nebutra.com";function As(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function Xn(e,t={}){As(t)||(async()=>{try{let n=await import("./dist-B346V4U6.js");if(typeof n.createProductAnalyticsClient!="function")return;let o=n.createProductAnalyticsClient({posthog:{apiKey:process.env.POSTHOG_KEY??process.env.NEXT_PUBLIC_POSTHOG_KEY??process.env.NEBUTRA_POSTHOG_KEY??"",host:process.env.POSTHOG_HOST??process.env.NEXT_PUBLIC_POSTHOG_HOST??process.env.NEBUTRA_POSTHOG_HOST??ws},onError:()=>{}});if(typeof o?.track!="function")return;let r=o.track("scaffold.completed",e);r&&typeof r.then=="function"&&await r.catch(()=>{})}catch{}})()}import q from"fs";import N from"path";function V(e){q.existsSync(e)&&q.rmSync(e,{recursive:!0,force:!0})}function St(e,t){let n=N.join(e,".env.example");q.existsSync(n)?q.appendFileSync(n,`
274
+ `+t):q.writeFileSync(n,t)}function ht(e,t){if(!q.existsSync(e))return;let n=q.readFileSync(e,"utf8"),o=n.replace(/export type AuthProviderId\s*=\s*(?:"[^"]+"\s*\|\s*)+"[^"]+";/,`export type AuthProviderId = "${t}";`);o!==n&&q.writeFileSync(e,o)}function Is(e,t){let n=N.join(e,"README.md");if(!q.existsSync(n)){q.writeFileSync(n,t);return}q.appendFileSync(n,`
275
+ `+t)}async function zn(e,t){let n=N.join(e,"packages","iam","auth");if(!q.existsSync(n))return;if(t==="none"){V(n),Is(e,`
276
276
  ## Auth
277
277
 
278
278
  Auth was skipped at scaffold time (\`--auth=none\`). Add your preferred auth provider manually (e.g. Clerk, Better Auth, NextAuth, Supabase).
279
- `);return}let o=N.join(n,"src","providers"),s=N.join(n,"src","types.ts");if(t==="clerk"){V(N.join(o,"better-auth.ts")),V(N.join(o,"nextauth.ts")),V(N.join(o,"supabase.ts")),St(s,"clerk"),yt(e,`# Clerk auth
279
+ `);return}let o=N.join(n,"src","providers"),r=N.join(n,"src","types.ts");if(t==="clerk"){V(N.join(o,"better-auth.ts")),V(N.join(o,"nextauth.ts")),V(N.join(o,"supabase.ts")),ht(r,"clerk"),St(e,`# Clerk auth
280
280
  CLERK_PUBLISHABLE_KEY=
281
281
  CLERK_SECRET_KEY=
282
- `);return}if(t==="betterauth"){V(N.join(o,"clerk.ts")),V(N.join(o,"nextauth.ts")),V(N.join(o,"supabase.ts")),St(s,"better-auth"),yt(e,`# Better Auth
282
+ `);return}if(t==="betterauth"){V(N.join(o,"clerk.ts")),V(N.join(o,"nextauth.ts")),V(N.join(o,"supabase.ts")),ht(r,"better-auth"),St(e,`# Better Auth
283
283
  BETTER_AUTH_SECRET=
284
284
  BETTER_AUTH_URL=http://localhost:3000
285
- `);return}if(t==="nextauth"){V(N.join(o,"clerk.ts")),V(N.join(o,"better-auth.ts")),V(N.join(o,"supabase.ts")),St(s,"nextauth"),yt(e,`# NextAuth (Auth.js v5)
285
+ `);return}if(t==="nextauth"){V(N.join(o,"clerk.ts")),V(N.join(o,"better-auth.ts")),V(N.join(o,"supabase.ts")),ht(r,"nextauth"),St(e,`# NextAuth (Auth.js v5)
286
286
  AUTH_SECRET=
287
287
  NEXTAUTH_URL=http://localhost:3000
288
288
  # OAuth (optional \u2014 leave blank to disable that provider)
@@ -290,7 +290,7 @@ GOOGLE_CLIENT_ID=
290
290
  GOOGLE_CLIENT_SECRET=
291
291
  GITHUB_CLIENT_ID=
292
292
  GITHUB_CLIENT_SECRET=
293
- `);return}if(t==="supabase"){V(N.join(o,"clerk.ts")),V(N.join(o,"better-auth.ts")),V(N.join(o,"nextauth.ts")),St(s,"supabase"),yt(e,`# Supabase Auth
293
+ `);return}if(t==="supabase"){V(N.join(o,"clerk.ts")),V(N.join(o,"better-auth.ts")),V(N.join(o,"nextauth.ts")),ht(r,"supabase"),St(e,`# Supabase Auth
294
294
  NEXT_PUBLIC_SUPABASE_URL=
295
295
  NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=
296
296
  NEXT_PUBLIC_SUPABASE_ANON_KEY=
@@ -298,7 +298,7 @@ SUPABASE_URL=
298
298
  SUPABASE_PUBLISHABLE_KEY=
299
299
  SUPABASE_ANON_KEY=
300
300
  SUPABASE_SERVICE_ROLE_KEY=
301
- `);return}}import Ce from"fs";import Ie from"path";function Cr(e,t){let n=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
301
+ `);return}}import xe from"fs";import Ce from"path";function Cs(e,t){let n=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
302
302
  // Generated by create-sailor \u2014 OAuth callback for ${e.name}
303
303
  // Primary auth provider: ${t}
304
304
  // Docs: ${e.docs}`,o={wechat:` const tokenRes = await fetch(
@@ -423,7 +423,7 @@ ${o[e.id]}
423
423
  void state;
424
424
  return NextResponse.redirect(new URL("/dashboard", req.url));
425
425
  }
426
- `}function xr(e){return`"use client";
426
+ `}function xs(e){return`"use client";
427
427
 
428
428
  /**
429
429
  * SocialLoginButtons \u2014 generated by create-sailor.
@@ -466,23 +466,23 @@ export function SocialLoginButtons() {
466
466
  </div>
467
467
  );
468
468
  }
469
- `}function Jn(e){Ce.mkdirSync(e,{recursive:!0})}function Rr(e,t){let n=Ie.join(e,".env.example");Ce.existsSync(n)?Ce.appendFileSync(n,`
470
- `+t):Ce.writeFileSync(n,t)}function kr(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,n=e.envVars.map(o=>`${o}=`).join(`
469
+ `}function Jn(e){xe.mkdirSync(e,{recursive:!0})}function Rs(e,t){let n=Ce.join(e,".env.example");xe.existsSync(n)?xe.appendFileSync(n,`
470
+ `+t):xe.writeFileSync(n,t)}function ks(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,n=e.envVars.map(o=>`${o}=`).join(`
471
471
  `);return`${t}
472
472
  ${n}
473
- `}async function Qn(e,t,n){if(!t||t.length===0)return;let o=Ie.join(e,"apps","web");if(!Ce.existsSync(o))return;let s=new Set,r=[];for(let l of t){if(s.has(l))continue;s.add(l);let u=Un(l);u&&r.push(u)}if(r.length===0)return;for(let l of r)Rr(e,kr(l));let i=Ie.join(o,"src","app","api","auth","callback");for(let l of r){let u=Ie.join(i,l.id);Jn(u);let d=Ie.join(u,"route.ts");Ce.writeFileSync(d,Cr(l,n))}let a=Ie.join(o,"src","components","auth");Jn(a);let c=Ie.join(a,"SocialLoginButtons.tsx");Ce.writeFileSync(c,xr(r))}import ze from"fs";import eo from"path";var ht=[{id:"upstash-redis",name:"Upstash Redis",region:"both",envVars:["UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN"],docs:"https://upstash.com/docs/redis",description:"Serverless Redis"},{id:"vercel-kv",name:"Vercel KV",region:"global",envVars:["KV_URL","KV_REST_API_URL","KV_REST_API_TOKEN","KV_REST_API_READ_ONLY_TOKEN"],docs:"https://vercel.com/docs/storage/vercel-kv",description:"Vercel native KV"},{id:"redis",name:"Redis (self-hosted)",region:"both",envVars:["REDIS_URL"],docs:"https://redis.io/docs/",description:"Self-hosted Redis"},{id:"dragonfly",name:"Dragonfly",region:"global",envVars:["DRAGONFLY_URL"],docs:"https://www.dragonflydb.io/docs",description:"Drop-in Redis replacement, faster"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip cache package"}];function Zn(e){return ht.find(t=>t.id===e)}var jp=ht.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import ne from"fs";import Et from"path";function oe(e,t){let n=Et.join(e,".env.example");if(!ne.existsSync(n)||t.envVars.length===0)return;let s=`# ${t.category??t.name}: ${t.name}`;if(ne.readFileSync(n,"utf-8").includes(s))return;let a=["","# =============================================",s,t.docs?`# Docs: ${t.docs}`:null,"# =============================================",...t.envVars.map(c=>`${c}=""`),""].filter(c=>c!==null).join(`
474
- `);ne.appendFileSync(n,a)}function se(e,t,n){let o=Et.join(e,".env.example");if(!ne.existsSync(o))return;let s=ne.readFileSync(o,"utf-8"),r=`${t}="${n}"`,i=new RegExp(`^${t}=.*$`,"m");if(i.test(s)){ne.writeFileSync(o,s.replace(i,r));return}let a=s.endsWith(`
473
+ `}async function Qn(e,t,n){if(!t||t.length===0)return;let o=Ce.join(e,"apps","web");if(!xe.existsSync(o))return;let r=new Set,s=[];for(let p of t){if(r.has(p))continue;r.add(p);let u=Un(p);u&&s.push(u)}if(s.length===0)return;for(let p of s)Rs(e,ks(p));let i=Ce.join(o,"src","app","api","auth","callback");for(let p of s){let u=Ce.join(i,p.id);Jn(u);let d=Ce.join(u,"route.ts");xe.writeFileSync(d,Cs(p,n))}let a=Ce.join(o,"src","components","auth");Jn(a);let c=Ce.join(a,"SocialLoginButtons.tsx");xe.writeFileSync(c,xs(s))}import Je from"fs";import eo from"path";var Et=[{id:"upstash-redis",name:"Upstash Redis",region:"both",envVars:["UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN"],docs:"https://upstash.com/docs/redis",description:"Serverless Redis"},{id:"vercel-kv",name:"Vercel KV",region:"global",envVars:["KV_URL","KV_REST_API_URL","KV_REST_API_TOKEN","KV_REST_API_READ_ONLY_TOKEN"],docs:"https://vercel.com/docs/storage/vercel-kv",description:"Vercel native KV"},{id:"redis",name:"Redis (self-hosted)",region:"both",envVars:["REDIS_URL"],docs:"https://redis.io/docs/",description:"Self-hosted Redis"},{id:"dragonfly",name:"Dragonfly",region:"global",envVars:["DRAGONFLY_URL"],docs:"https://www.dragonflydb.io/docs",description:"Drop-in Redis replacement, faster"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip cache package"}];function Zn(e){return Et.find(t=>t.id===e)}var Vp=Et.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import ne from"fs";import vt from"path";function oe(e,t){let n=vt.join(e,".env.example");if(!ne.existsSync(n)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(ne.readFileSync(n,"utf-8").includes(r))return;let a=["","# =============================================",r,t.docs?`# Docs: ${t.docs}`:null,"# =============================================",...t.envVars.map(c=>`${c}=""`),""].filter(c=>c!==null).join(`
474
+ `);ne.appendFileSync(n,a)}function re(e,t,n){let o=vt.join(e,".env.example");if(!ne.existsSync(o))return;let r=ne.readFileSync(o,"utf-8"),s=`${t}="${n}"`,i=new RegExp(`^${t}=.*$`,"m");if(i.test(r)){ne.writeFileSync(o,r.replace(i,s));return}let a=r.endsWith(`
475
475
  `)?"":`
476
- `;ne.appendFileSync(o,`${a}${r}
477
- `)}var Tr=["design","iam","commerce","integrations","platform","ops","ai"];function xe(e,t){for(let o of Tr){let s=Et.join(e,"packages",o,t);if(ne.existsSync(s))return s}let n=Et.join(e,"packages",t);return ne.existsSync(n)?n:null}function z(e,t){let n=xe(e,t);n&&ne.rmSync(n,{recursive:!0,force:!0})}function to(e){return ze.existsSync(e)?ze.readFileSync(e,"utf-8"):null}function Nr(e,t){let n=eo.join(e,".env.example"),o=to(n);if(o===null)return;let s=`# Cache: ${t.name}`;if(o.includes(s))return;let r=["","# =============================================",s,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
478
- `);ze.appendFileSync(n,r)}function Or(e,t,n){let o=eo.join(e,".env.example"),s=to(o);if(s===null)return;let r=new RegExp(`^${t}=.*$`,"m");r.test(s)?ze.writeFileSync(o,s.replace(r,`${t}="${n}"`)):ze.appendFileSync(o,`${t}="${n}"
479
- `)}async function no(e,t,n){let o=xe(e,"cache");if(t==="none"){o&&ze.rmSync(o,{recursive:!0,force:!0});return}let s=Zn(t);if(!s)throw new Error(`Unknown cache provider "${t}". Valid ids: ${ht.map(r=>r.id).join(", ")}`);o&&(Nr(e,s),Or(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 oo(e){return vt.find(t=>t.id===e)}var Xp=vt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function so(e,t,n="global"){let o=oo(t);if(!o)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${vt.map(s=>s.id).join(", ")}`);if(o.id==="none"){z(e,"captcha");return}o.envVars.length>0&&oe(e,{category:"Captcha",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"CAPTCHA_PROVIDER",o.id)}import _t from"fs";import Lr from"path";var bt=[{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 ro(e){return bt.find(t=>t.id===e)}var el=bt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function io(e,t,n="global"){let o=ro(t);if(!o)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${bt.map(r=>r.id).join(", ")}`);let s=Lr.join(e,"apps","studio");if(o.id==="none"){z(e,"sanity"),_t.existsSync(s)&&_t.rmSync(s,{recursive:!0,force:!0});return}o.id!=="sanity"&&(z(e,"sanity"),_t.existsSync(s)&&_t.rmSync(s,{recursive:!0,force:!0})),o.envVars.length>0&&oe(e,{category:"CMS",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"CMS_PROVIDER",o.id)}import U from"fs";import O from"path";var Ur=O.join("apps","web"),sn=O.join("src","components","compliance"),it=O.join("src","app","[locale]");function re(e){return O.join(e,Ur)}function Mr(e){U.mkdirSync(e,{recursive:!0})}function J(e,t){Mr(O.dirname(e)),U.writeFileSync(e,t,"utf8")}function rn(e,t){let n=O.join(e,".env.example");if(U.existsSync(n)){if(U.readFileSync(n,"utf8").includes(t.split(`
476
+ `;ne.appendFileSync(o,`${a}${s}
477
+ `)}var Ts=["design","iam","commerce","integrations","platform","ops","ai"];function Re(e,t){for(let o of Ts){let r=vt.join(e,"packages",o,t);if(ne.existsSync(r))return r}let n=vt.join(e,"packages",t);return ne.existsSync(n)?n:null}function z(e,t){let n=Re(e,t);n&&ne.rmSync(n,{recursive:!0,force:!0})}function to(e){return Je.existsSync(e)?Je.readFileSync(e,"utf-8"):null}function Ns(e,t){let n=eo.join(e,".env.example"),o=to(n);if(o===null)return;let r=`# Cache: ${t.name}`;if(o.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
478
+ `);Je.appendFileSync(n,s)}function Os(e,t,n){let o=eo.join(e,".env.example"),r=to(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?Je.writeFileSync(o,r.replace(s,`${t}="${n}"`)):Je.appendFileSync(o,`${t}="${n}"
479
+ `)}async function no(e,t,n){let o=Re(e,"cache");if(t==="none"){o&&Je.rmSync(o,{recursive:!0,force:!0});return}let r=Zn(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${Et.map(s=>s.id).join(", ")}`);o&&(Ns(e,r),Os(e,"CACHE_PROVIDER",t))}var bt=[{id:"turnstile",name:"Cloudflare Turnstile",region:"global",envVars:["NEXT_PUBLIC_TURNSTILE_SITE_KEY","TURNSTILE_SECRET_KEY"],docs:"https://developers.cloudflare.com/turnstile/",description:"Free, privacy-focused captcha alternative"},{id:"hcaptcha",name:"hCaptcha",region:"global",envVars:["NEXT_PUBLIC_HCAPTCHA_SITE_KEY","HCAPTCHA_SECRET_KEY"],docs:"https://docs.hcaptcha.com/",description:"Privacy-respecting captcha"},{id:"aliyun-slide",name:"\u963F\u91CC\u4E91\u9A8C\u8BC1\u7801 2.0",region:"cn",envVars:["ALIYUN_CAPTCHA_ACCESS_KEY_ID","ALIYUN_CAPTCHA_ACCESS_KEY_SECRET","ALIYUN_CAPTCHA_APP_KEY","NEXT_PUBLIC_ALIYUN_CAPTCHA_APP_KEY"],docs:"https://help.aliyun.com/product/28308.html",description:"\u963F\u91CC\u4E91\u667A\u80FD\u9A8C\u8BC1 (\u6ED1\u5757/\u65E0\u75D5)"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function oo(e){return bt.find(t=>t.id===e)}var Jp=bt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function ro(e,t,n="global"){let o=oo(t);if(!o)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${bt.map(r=>r.id).join(", ")}`);if(o.id==="none"){z(e,"captcha");return}o.envVars.length>0&&oe(e,{category:"Captcha",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"CAPTCHA_PROVIDER",o.id)}import Pt from"fs";import Ls 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 so(e){return _t.find(t=>t.id===e)}var nl=_t.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function io(e,t,n="global"){let o=so(t);if(!o)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${_t.map(s=>s.id).join(", ")}`);let r=Ls.join(e,"apps","studio");if(o.id==="none"){z(e,"sanity"),Pt.existsSync(r)&&Pt.rmSync(r,{recursive:!0,force:!0});return}o.id!=="sanity"&&(z(e,"sanity"),Pt.existsSync(r)&&Pt.rmSync(r,{recursive:!0,force:!0})),o.envVars.length>0&&oe(e,{category:"CMS",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"CMS_PROVIDER",o.id)}import U from"fs";import O from"path";var Us=O.join("apps","web"),rn=O.join("src","components","compliance"),at=O.join("src","app","[locale]");function se(e){return O.join(e,Us)}function Ms(e){U.mkdirSync(e,{recursive:!0})}function J(e,t){Ms(O.dirname(e)),U.writeFileSync(e,t,"utf8")}function sn(e,t){let n=O.join(e,".env.example");if(U.existsSync(n)){if(U.readFileSync(n,"utf8").includes(t.split(`
480
480
  `)[0]??""))return;U.appendFileSync(n,`
481
481
  `+t+`
482
482
  `)}else U.writeFileSync(n,t+`
483
- `)}var at=`> **TEMPLATE \u2014 NOT LEGAL ADVICE.** This document is a boilerplate scaffold only.
483
+ `)}var ct=`> **TEMPLATE \u2014 NOT LEGAL ADVICE.** This document is a boilerplate scaffold only.
484
484
  > Consult a qualified lawyer in every jurisdiction you operate in before publishing.
485
- > \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`,Dr=`import Link from "next/link";
485
+ > \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`,Ds=`import Link from "next/link";
486
486
  import { IcpFooter } from "@/components/compliance/IcpFooter";
487
487
  import { PublicSecurityFooter } from "@/components/compliance/PublicSecurityFooter";
488
488
 
@@ -533,7 +533,7 @@ export function Footer({ region = "global" }: FooterProps) {
533
533
  </footer>
534
534
  );
535
535
  }
536
- `,Fr=`export function IcpFooter() {
536
+ `,Fs=`export function IcpFooter() {
537
537
  const icp = process.env.NEXT_PUBLIC_ICP_BEIAN;
538
538
  if (!icp) return null;
539
539
  return (
@@ -547,7 +547,7 @@ export function Footer({ region = "global" }: FooterProps) {
547
547
  </a>
548
548
  );
549
549
  }
550
- `,jr=`export function PublicSecurityFooter() {
550
+ `,js=`export function PublicSecurityFooter() {
551
551
  const psb = process.env.NEXT_PUBLIC_PSB_BEIAN;
552
552
  const psbCode = process.env.NEXT_PUBLIC_PSB_CODE;
553
553
  if (!psb) return null;
@@ -564,7 +564,7 @@ export function Footer({ region = "global" }: FooterProps) {
564
564
  </a>
565
565
  );
566
566
  }
567
- `,Br=`"use client";
567
+ `,Bs=`"use client";
568
568
 
569
569
  import { useEffect, useState } from "react";
570
570
 
@@ -718,7 +718,7 @@ export function CookieBanner() {
718
718
  </div>
719
719
  );
720
720
  }
721
- `,Vr=`interface AigcDisclaimerProps {
721
+ `,Vs=`interface AigcDisclaimerProps {
722
722
  className?: string;
723
723
  }
724
724
 
@@ -738,13 +738,13 @@ export function AigcDisclaimer({ className }: AigcDisclaimerProps) {
738
738
  </div>
739
739
  );
740
740
  }
741
- `,Kr=`---
741
+ `,Ks=`---
742
742
  title: Privacy Policy / \u9690\u79C1\u653F\u7B56
743
743
  description: How {{COMPANY_NAME}} collects, uses, shares, and protects personal information.
744
744
  lastUpdated: 2026-01-01
745
745
  ---
746
746
 
747
- ${at}
747
+ ${ct}
748
748
 
749
749
  # Privacy Policy / \u9690\u79C1\u653F\u7B56
750
750
 
@@ -883,13 +883,13 @@ or in-app notification before the change takes effect.
883
883
  **Data Controller / \u6570\u636E\u63A7\u5236\u8005:** {{COMPANY_NAME}}
884
884
  **Address / \u5730\u5740:** {{COMPANY_ADDRESS}}
885
885
  **Email / \u90AE\u7BB1:** {{COMPANY_CONTACT_EMAIL}}
886
- `,$r=`---
886
+ `,$s=`---
887
887
  title: Terms of Service / \u670D\u52A1\u6761\u6B3E
888
888
  description: Terms governing your use of {{COMPANY_NAME}}.
889
889
  lastUpdated: 2026-01-01
890
890
  ---
891
891
 
892
- ${at}
892
+ ${ct}
893
893
 
894
894
  # Terms of Service / \u670D\u52A1\u6761\u6B3E
895
895
 
@@ -1002,13 +1002,13 @@ conflict-of-laws principles. Disputes shall be resolved in the competent courts
1002
1002
  ## 11. Contact / \u8054\u7CFB\u65B9\u5F0F
1003
1003
 
1004
1004
  {{COMPANY_NAME}} \xB7 {{COMPANY_ADDRESS}} \xB7 {{COMPANY_CONTACT_EMAIL}}
1005
- `,Yr=`---
1005
+ `,Ys=`---
1006
1006
  title: AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
1007
1007
  description: Disclosure required by \u7F51\u4FE1\u529E\u300A\u751F\u6210\u5F0F\u4EBA\u5DE5\u667A\u80FD\u670D\u52A1\u7BA1\u7406\u6682\u884C\u529E\u6CD5\u300B
1008
1008
  lastUpdated: 2026-01-01
1009
1009
  ---
1010
1010
 
1011
- ${at}
1011
+ ${ct}
1012
1012
 
1013
1013
  # AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
1014
1014
 
@@ -1084,13 +1084,13 @@ human professional.
1084
1084
 
1085
1085
  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
1086
1086
  \u7528\u4E8E\u533B\u7597\u3001\u6CD5\u5F8B\u3001\u91D1\u878D\u6216\u5B89\u5168\u6538\u5173\u7684\u51B3\u7B56\u3002
1087
- `,qr=`---
1087
+ `,qs=`---
1088
1088
  title: Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
1089
1089
  description: Notice of cross-border transfer of personal information, per PIPL.
1090
1090
  lastUpdated: 2026-01-01
1091
1091
  ---
1092
1092
 
1093
- ${at}
1093
+ ${ct}
1094
1094
 
1095
1095
  # Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
1096
1096
 
@@ -1149,13 +1149,13 @@ Refusal may limit your ability to use features that rely on overseas services.
1149
1149
  - \u4F20\u8F93\u4E2D\u52A0\u5BC6 (TLS 1.2+) \u53CA\u9759\u6001\u52A0\u5BC6 (AES-256)\u3002
1150
1150
  - \u5408\u540C\u6761\u6B3E\u8981\u6C42\u5883\u5916\u63A5\u6536\u65B9\u63D0\u4F9B\u7B49\u540C\u4E8E PIPL \u7684\u4FDD\u62A4\u3002
1151
1151
  - \u8BBF\u95EE\u63A7\u5236\u3001\u5BA1\u8BA1\u65E5\u5FD7\u548C\u8FDD\u89C4\u901A\u77E5\u7A0B\u5E8F\u3002
1152
- `,Gr=`---
1152
+ `,Gs=`---
1153
1153
  title: Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
1154
1154
  description: Itemized list of personal information collected, per PIPL Article 17.
1155
1155
  lastUpdated: 2026-01-01
1156
1156
  ---
1157
1157
 
1158
- ${at}
1158
+ ${ct}
1159
1159
 
1160
1160
  # Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
1161
1161
 
@@ -1191,23 +1191,23 @@ To exercise your rights (access, rectify, delete, export, withdraw consent), con
1191
1191
  **{{COMPANY_CONTACT_EMAIL}}**.
1192
1192
 
1193
1193
  \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
1194
- `;async function Hr(e,t){let n=re(e);if(!U.existsSync(n))return;let o=O.join(n,"src","components","compliance","Footer.tsx");J(o,Dr);let s=O.join(n,"src","components","compliance","README.md");J(s,["# 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(`
1195
- `))}async function Wr(e,t){let n=re(e);if(!U.existsSync(n))return;let o=O.join(n,"src","components","compliance","CookieBanner.tsx");J(o,Br)}async function Xr(e,t){let n=re(e);if(!U.existsSync(n))return;let o=O.join(n,it,"privacy","page.mdx");J(o,Kr)}async function zr(e,t){let n=re(e);if(!U.existsSync(n))return;let o=O.join(n,it,"terms","page.mdx");J(o,$r)}async function Jr(e){let t=re(e);if(!U.existsSync(t))return;let n=O.join(t,sn,"IcpFooter.tsx");J(n,Fr),rn(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(`
1196
- `))}async function Qr(e){let t=re(e);if(!U.existsSync(t))return;let n=O.join(t,sn,"PublicSecurityFooter.tsx");J(n,jr),rn(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(`
1197
- `))}async function Zr(e){let t=re(e);if(!U.existsSync(t))return;let n=O.join(t,sn,"AigcDisclaimer.tsx");J(n,Vr),rn(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(`
1198
- `))}async function ei(e){let t=re(e);if(!U.existsSync(t))return;let n=O.join(t,it,"aigc-disclosure","page.mdx");J(n,Yr)}async function ti(e){let t=re(e);if(!U.existsSync(t))return;let n=O.join(t,it,"cross-border-data","page.mdx");J(n,qr)}async function ni(e){let t=re(e);if(!U.existsSync(t))return;let n=O.join(t,it,"pii-collection","page.mdx");J(n,Gr)}async function ao(e,t){try{await Hr(e,t),await Wr(e,t),await Xr(e,t),await zr(e,t),(t==="cn"||t==="hybrid")&&(await Jr(e),await Qr(e),await Zr(e),await ei(e),await ti(e),await ni(e))}catch(n){throw console.error("applyComplianceTemplates failed:",n),new Error(`Failed to apply compliance templates for region "${t}". Check that ${e} is writable.`)}}import oi from"fs";import si from"path";async function co(e,t){let n=si.join(e,"nebutra.config.json");oi.writeFileSync(n,JSON.stringify(t,null,2)+`
1199
- `)}import R from"fs";import Re from"path";function ri(e){R.existsSync(e)&&R.rmSync(e,{recursive:!0,force:!0})}function po(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function ii(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function lo(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 ai(e,t){let n=Re.join(e,".env.example");R.existsSync(n)?R.appendFileSync(n,`
1200
- `+t):R.writeFileSync(n,t)}async function uo(e,t,n){let o=Re.join(e,"packages","platform","db");if(t==="none"){ri(o);return}let s=Re.join(o,"prisma","schema.prisma"),r;if(t==="postgresql"?r=`postgresql://postgres:postgres@localhost:5432/${n}`:t==="mysql"?r=`mysql://root:root@localhost:3306/${n}`:r="file:./dev.db",ai(e,`# Database (${t})
1201
- DATABASE_URL="${r}"
1202
- `),!R.existsSync(s))return;let i=R.readFileSync(s,"utf8"),a=i;t==="mysql"?(a=po(a,"mysql"),a=lo(a)):t==="sqlite"&&(a=po(a,"sqlite"),a=ii(a),a=lo(a)),a!==i&&R.writeFileSync(s,a)}function ci(e){let t=Re.join(e,".env.example");return R.existsSync(t)?R.readFileSync(t,"utf8"):""}function pi(e,t,n,o){let s=Re.join(e,".env.example"),r=ci(e),i=o?`# ${o}
1194
+ `;async function Hs(e,t){let n=se(e);if(!U.existsSync(n))return;let o=O.join(n,"src","components","compliance","Footer.tsx");J(o,Ds);let r=O.join(n,"src","components","compliance","README.md");J(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(`
1195
+ `))}async function Ws(e,t){let n=se(e);if(!U.existsSync(n))return;let o=O.join(n,"src","components","compliance","CookieBanner.tsx");J(o,Bs)}async function Xs(e,t){let n=se(e);if(!U.existsSync(n))return;let o=O.join(n,at,"privacy","page.mdx");J(o,Ks)}async function zs(e,t){let n=se(e);if(!U.existsSync(n))return;let o=O.join(n,at,"terms","page.mdx");J(o,$s)}async function Js(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,rn,"IcpFooter.tsx");J(n,Fs),sn(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(`
1196
+ `))}async function Qs(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,rn,"PublicSecurityFooter.tsx");J(n,js),sn(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(`
1197
+ `))}async function Zs(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,rn,"AigcDisclaimer.tsx");J(n,Vs),sn(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(`
1198
+ `))}async function ei(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,at,"aigc-disclosure","page.mdx");J(n,Ys)}async function ti(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,at,"cross-border-data","page.mdx");J(n,qs)}async function ni(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,at,"pii-collection","page.mdx");J(n,Gs)}async function ao(e,t){try{await Hs(e,t),await Ws(e,t),await Xs(e,t),await zs(e,t),(t==="cn"||t==="hybrid")&&(await Js(e),await Qs(e),await Zs(e),await ei(e),await ti(e),await ni(e))}catch(n){throw console.error("applyComplianceTemplates failed:",n),new Error(`Failed to apply compliance templates for region "${t}". Check that ${e} is writable.`)}}import oi from"fs";import ri from"path";async function co(e,t){let n=ri.join(e,"nebutra.config.json");oi.writeFileSync(n,JSON.stringify(t,null,2)+`
1199
+ `)}import R from"fs";import ke from"path";function si(e){R.existsSync(e)&&R.rmSync(e,{recursive:!0,force:!0})}function po(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function ii(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function lo(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 ai(e,t){let n=ke.join(e,".env.example");R.existsSync(n)?R.appendFileSync(n,`
1200
+ `+t):R.writeFileSync(n,t)}async function uo(e,t,n){let o=ke.join(e,"packages","platform","db");if(t==="none"){si(o);return}let r=ke.join(o,"prisma","schema.prisma"),s;if(t==="postgresql"?s=`postgresql://postgres:postgres@localhost:5432/${n}`:t==="mysql"?s=`mysql://root:root@localhost:3306/${n}`:s="file:./dev.db",ai(e,`# Database (${t})
1201
+ DATABASE_URL="${s}"
1202
+ `),!R.existsSync(r))return;let i=R.readFileSync(r,"utf8"),a=i;t==="mysql"?(a=po(a,"mysql"),a=lo(a)):t==="sqlite"&&(a=po(a,"sqlite"),a=ii(a),a=lo(a)),a!==i&&R.writeFileSync(r,a)}function ci(e){let t=ke.join(e,".env.example");return R.existsSync(t)?R.readFileSync(t,"utf8"):""}function pi(e,t,n,o){let r=ke.join(e,".env.example"),s=ci(e),i=o?`# ${o}
1203
1203
  ${t}="${n}"
1204
1204
  `:`${t}="${n}"
1205
- `,a=new RegExp(`^\\s*${t}\\s*=.*$`,"m");if(a.test(r)){R.writeFileSync(s,r.replace(a,`${t}="${n}"`));return}r?R.appendFileSync(s,`
1206
- ${i}`):R.writeFileSync(s,i)}function li(e,t){let n=Re.join(e,"packages","platform","db","prisma","schema.prisma");if(!R.existsSync(n))return;let o=R.readFileSync(n,"utf8"),s=/(datasource\s+db\s*\{[^}]*?)(\n})/;if(!o.match(s))return;let i=t.filter(l=>!o.includes(l.trim()));if(i.length===0)return;let a=i.map(l=>` ${l}`).join(`
1207
- `),c=o.replace(s,`$1
1208
- ${a}$2`);R.writeFileSync(n,c)}function di(e){let t=Re.join(e,"packages","platform","db","prisma","schema.prisma");if(!R.existsSync(t))return;let n=R.readFileSync(t,"utf8");if(/directUrl\s*=\s*env\(/.test(n))return;let o=/(datasource\s+db\s*\{[\s\S]*?url\s*=\s*env\(\s*"DATABASE_URL"\s*\)[^\n]*\n)/;o.test(n)&&R.writeFileSync(t,n.replace(o,`$1 directUrl = env("DIRECT_URL")
1209
- `))}async function mo(e,t,n){if(!(t.id==="none"||t.id==="local")){for(let o of t.envVars){let s=o.placeholder.replace(/\$PROJECT/g,n);pi(e,o.name,s,o.comment)}t.prismaDatasourceExtras&&t.prismaDatasourceExtras.length>0&&li(e,t.prismaDatasourceExtras),t.keepDirectUrl&&di(e)}}import ve from"fs";import ke from"path";import{fileURLToPath as ui}from"url";var mi=ui(import.meta.url),go=ke.dirname(mi),gi=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,fo=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function fi(e){let t=[ke.join(go,"..","templates","docs",e),ke.join(go,"..","..","templates","docs",e)];for(let n of t)if(ve.existsSync(n))return n;return t[0]}async function yo(e,t){if(t.framework==="none")return;if(!fo.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${fo.join(", ")}, none.`);let n=fi(t.framework),o=ke.join(e,"apps","docs");if(!ve.existsSync(n))throw new Error(`Docs template not found: ${n}`);So(n,o),ho(o,{"{PRODUCT_NAME}":t.projectName})}function So(e,t){ve.mkdirSync(t,{recursive:!0});for(let n of ve.readdirSync(e,{withFileTypes:!0})){let o=ke.join(e,n.name),s=ke.join(t,n.name);n.isDirectory()?So(o,s):ve.copyFileSync(o,s)}}function ho(e,t){for(let n of ve.readdirSync(e,{withFileTypes:!0})){let o=ke.join(e,n.name);if(n.isDirectory())ho(o,t);else if(gi.test(n.name)){let s=ve.readFileSync(o,"utf-8");for(let[r,i]of Object.entries(t))s=s.split(r).join(i);ve.writeFileSync(o,s)}}}import Ne from"fs";import Te from"path";var Pt=[{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 Eo(e){return Pt.find(t=>t.id===e)}var bl=Pt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Oe="@nebutra/email";function an(e,t){Ne.mkdirSync(Te.dirname(e),{recursive:!0}),Ne.writeFileSync(e,t)}function yi(e,t){let n=Te.join(e,".env.example");Ne.existsSync(n)?Ne.appendFileSync(n,`
1210
- `+t):Ne.writeFileSync(n,t)}function Si(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
1205
+ `,a=new RegExp(`^\\s*${t}\\s*=.*$`,"m");if(a.test(s)){R.writeFileSync(r,s.replace(a,`${t}="${n}"`));return}s?R.appendFileSync(r,`
1206
+ ${i}`):R.writeFileSync(r,i)}function li(e,t){let n=ke.join(e,"packages","platform","db","prisma","schema.prisma");if(!R.existsSync(n))return;let o=R.readFileSync(n,"utf8"),r=/(datasource\s+db\s*\{[^}]*?)(\n})/;if(!o.match(r))return;let i=t.filter(p=>!o.includes(p.trim()));if(i.length===0)return;let a=i.map(p=>` ${p}`).join(`
1207
+ `),c=o.replace(r,`$1
1208
+ ${a}$2`);R.writeFileSync(n,c)}function di(e){let t=ke.join(e,"packages","platform","db","prisma","schema.prisma");if(!R.existsSync(t))return;let n=R.readFileSync(t,"utf8");if(/directUrl\s*=\s*env\(/.test(n))return;let o=/(datasource\s+db\s*\{[\s\S]*?url\s*=\s*env\(\s*"DATABASE_URL"\s*\)[^\n]*\n)/;o.test(n)&&R.writeFileSync(t,n.replace(o,`$1 directUrl = env("DIRECT_URL")
1209
+ `))}async function mo(e,t,n){if(!(t.id==="none"||t.id==="local")){for(let o of t.envVars){let r=o.placeholder.replace(/\$PROJECT/g,n);pi(e,o.name,r,o.comment)}t.prismaDatasourceExtras&&t.prismaDatasourceExtras.length>0&&li(e,t.prismaDatasourceExtras),t.keepDirectUrl&&di(e)}}import ve from"fs";import Te from"path";import{fileURLToPath as ui}from"url";var mi=ui(import.meta.url),go=Te.dirname(mi),gi=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,fo=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function fi(e){let t=[Te.join(go,"..","templates","docs",e),Te.join(go,"..","..","templates","docs",e)];for(let n of t)if(ve.existsSync(n))return n;return t[0]}async function yo(e,t){if(t.framework==="none")return;if(!fo.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${fo.join(", ")}, none.`);let n=fi(t.framework),o=Te.join(e,"apps","docs");if(!ve.existsSync(n))throw new Error(`Docs template not found: ${n}`);So(n,o),ho(o,{"{PRODUCT_NAME}":t.projectName})}function So(e,t){ve.mkdirSync(t,{recursive:!0});for(let n of ve.readdirSync(e,{withFileTypes:!0})){let o=Te.join(e,n.name),r=Te.join(t,n.name);n.isDirectory()?So(o,r):ve.copyFileSync(o,r)}}function ho(e,t){for(let n of ve.readdirSync(e,{withFileTypes:!0})){let o=Te.join(e,n.name);if(n.isDirectory())ho(o,t);else if(gi.test(n.name)){let r=ve.readFileSync(o,"utf-8");for(let[s,i]of Object.entries(t))r=r.split(s).join(i);ve.writeFileSync(o,r)}}}import Oe from"fs";import Ne from"path";var wt=[{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 Eo(e){return wt.find(t=>t.id===e)}var Pl=wt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Le="@nebutra/email";function an(e,t){Oe.mkdirSync(Ne.dirname(e),{recursive:!0}),Oe.writeFileSync(e,t)}function yi(e,t){let n=Ne.join(e,".env.example");Oe.existsSync(n)?Oe.appendFileSync(n,`
1210
+ `+t):Oe.writeFileSync(n,t)}function Si(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
1211
1211
  `);return`${t}
1212
1212
  ${n}
1213
1213
  `}var hi=`/**
@@ -1231,7 +1231,7 @@ export interface SendEmailResult {
1231
1231
  raw?: unknown;
1232
1232
  }
1233
1233
  `;function Ei(){return`/**
1234
- * @${Oe.slice(1)} \u2014 Resend transactional email wrapper.
1234
+ * @${Le.slice(1)} \u2014 Resend transactional email wrapper.
1235
1235
  *
1236
1236
  * Docs: https://resend.com/docs
1237
1237
  */
@@ -1270,7 +1270,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1270
1270
 
1271
1271
  export type { SendEmailInput, SendEmailResult } from "./types";
1272
1272
  `}function vi(){return`/**
1273
- * @${Oe.slice(1)} \u2014 Postmark transactional email wrapper.
1273
+ * @${Le.slice(1)} \u2014 Postmark transactional email wrapper.
1274
1274
  *
1275
1275
  * Docs: https://postmarkapp.com/developer
1276
1276
  */
@@ -1308,7 +1308,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1308
1308
 
1309
1309
  export type { SendEmailInput, SendEmailResult } from "./types";
1310
1310
  `}function bi(){return`/**
1311
- * @${Oe.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1311
+ * @${Le.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1312
1312
  *
1313
1313
  * Docs: https://docs.aws.amazon.com/ses
1314
1314
  */
@@ -1364,7 +1364,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1364
1364
 
1365
1365
  export type { SendEmailInput, SendEmailResult } from "./types";
1366
1366
  `}function _i(){return`/**
1367
- * @${Oe.slice(1)} \u2014 \u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001 (Aliyun DirectMail) wrapper.
1367
+ * @${Le.slice(1)} \u2014 \u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001 (Aliyun DirectMail) wrapper.
1368
1368
  *
1369
1369
  * Docs: https://help.aliyun.com/product/29412.html
1370
1370
  */
@@ -1414,7 +1414,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1414
1414
 
1415
1415
  export type { SendEmailInput, SendEmailResult } from "./types";
1416
1416
  `}function Pi(){return`/**
1417
- * @${Oe.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1417
+ * @${Le.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1418
1418
  *
1419
1419
  * Docs: https://cloud.tencent.com/document/product/1288
1420
1420
  */
@@ -1462,7 +1462,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1462
1462
 
1463
1463
  export type { SendEmailInput, SendEmailResult } from "./types";
1464
1464
  `}function wi(){return`/**
1465
- * @${Oe.slice(1)} \u2014 \u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1 via SMTP (nodemailer).
1465
+ * @${Le.slice(1)} \u2014 \u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1 via SMTP (nodemailer).
1466
1466
  *
1467
1467
  * Docs: https://qiye.163.com/help
1468
1468
  */
@@ -1500,32 +1500,31 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1500
1500
 
1501
1501
  export type { SendEmailInput, SendEmailResult } from "./types";
1502
1502
  `}function Ai(e){switch(e){case"resend":return Ei();case"postmark":return vi();case"ses":return bi();case"aliyun-dm":return _i();case"tencent-ses":return Pi();case"netease":return wi();case"none":return`export {};
1503
- `}}function Ii(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),e.id==="aliyun-dm"&&(t["@alicloud/openapi-client"]="^0.4.12");let n={name:Oe,version:"0.1.0",private:!0,description:`Transactional email via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
1504
- `}async function vo(e,t,n){if(t==="none")return;let o=Eo(t);if(!o)throw new Error(`Unknown email provider "${t}". Valid ids: ${Pt.map(i=>i.id).join(", ")}`);let s=Te.join(e,"packages","email"),r=Te.join(s,"src");Ne.existsSync(r)&&Ne.rmSync(r,{recursive:!0,force:!0}),an(Te.join(s,"package.json"),Ii(o)),an(Te.join(r,"types.ts"),hi),an(Te.join(r,"index.ts"),Ai(o.id)),yi(e,Si(o))}import wt from"fs";import bo from"path";async function _o(e,t){let n=`# Automatically injected by create-sailor
1505
- DATABASE_URL="${String(t.databaseUrl)}"
1506
-
1507
- NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="${String(t.clerkPublishable)}"
1508
- CLERK_SECRET_KEY="${String(t.clerkSecret)}"
1509
-
1510
- NEXT_PUBLIC_SITE_URL="http://localhost:3000"
1511
- `,o=bo.join(e,".env"),s=bo.join(e,".env.local");!wt.existsSync(o)&&!wt.existsSync(s)?wt.writeFileSync(s,n):wt.appendFileSync(s,`
1512
- `+n)}import wo from"crypto";import ct from"fs";import Po from"path";function Le(e){return wo.randomBytes(e).toString("base64").replace(/=+$/,"")}function Ci(e){return wo.randomBytes(e).toString("hex")}function xi(){return{AUTH_SECRET:Le(32),NEXTAUTH_SECRET:Le(32),BETTER_AUTH_SECRET:Le(32),JWT_SECRET:Le(32),WEBHOOK_SECRET:Ci(16),ENCRYPTION_KEY:Le(32),API_SECRET_KEY:Le(32),SESSION_SECRET:Le(32)}}function Ri(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function ki(e,t,n){let o=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),s=Ri(n);return e.replace(o,`${t}="${s}"`)}async function Ao(e){let t=Po.join(e,".env.example"),n=Po.join(e,".env.local");if(!ct.existsSync(t))return null;try{let o=ct.readFileSync(t,"utf8"),s=xi(),i=ct.existsSync(n)?ct.readFileSync(n,"utf8"):o;for(let a of Object.keys(s))i=ki(i,a,s[a]);return ct.writeFileSync(n,i),s}catch(o){let s=o instanceof Error?o.message:String(o);throw console.error(`[create-sailor] Failed to generate env secrets: ${s}`),new Error(`Unable to write .env.local: ${s}`)}}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 Io(e){return At.find(t=>t.id===e)}var Ll=At.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Co(e,t,n="global"){let o=Io(t);if(!o)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${At.map(s=>s.id).join(", ")}`);if(o.id==="none"){z(e,"feature-flags");return}o.envVars.length>0&&oe(e,{category:"Feature Flags",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"FEATURE_FLAGS_PROVIDER",o.id)}import{execFileSync as To}from"child_process";import L from"fs";import Ti from"os";import ie from"path";import Ni from"ignore";var Oi={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 Li(){let e=process.env.SAILOR_TEMPLATE_LOCAL_DIR;if(!(!e||e.trim().length===0))return ie.resolve(e.trim())}var Ui=new Set(["node_modules",".git","dist",".next",".turbo"]);function Mi(e,t){if(!L.statSync(e).isDirectory())throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR is not a directory: ${e}`);L.cpSync(e,t,{recursive:!0,dereference:!0,filter:o=>{let s=ie.basename(o);return!Ui.has(s)}})}function Di(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function Fi(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function No(e){return/^[0-9a-f]{7,40}$/i.test(e)}function ji(e,t){let n=`https://github.com/${e}.git`,o=[`refs/heads/${t}`,`refs/tags/${t}`];for(let s of o)try{let r=To("git",["ls-remote",n,s],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!r)continue;let[i]=r.split(/\s+/);if(No(i))return i}catch{}return null}async function Bi(e,t){if(No(t))return t;let n=await fetch(`https://api.github.com/repos/${e}/commits/${encodeURIComponent(t)}`,{headers:{Accept:"application/vnd.github+json","User-Agent":"create-sailor"}});if(!n.ok){let s=ji(e,t);if(s)return s;throw new Error(`Failed to resolve ${e}@${t} (GitHub API ${n.status})`)}let o=await n.json();if(typeof o.sha!="string"||o.sha.length===0)throw new Error(`GitHub API did not return a commit SHA for ${e}@${t}`);return o.sha}function Oo(e,t,n){let o=L.readdirSync(t,{withFileTypes:!0});for(let s of o){if(s.name==="node_modules"||s.name===".git")continue;let r=ie.join(t,s.name),i=ie.relative(e,r).split(ie.sep).join("/");s.isDirectory()?(n.push(i+"/"),Oo(e,r,n)):n.push(i)}}function xo(e){let t=ie.join(e,".templateignore");if(!L.existsSync(t))return;let n=L.readFileSync(t,"utf8"),o=Ni().add(n),s=[];Oo(e,e,s);let r=s.map(c=>c.endsWith("/")?c.slice(0,-1):c),i=new Set(o.filter(r)),a=r.filter(c=>!i.has(c)).sort((c,l)=>l.split("/").length-c.split("/").length);for(let c of a){let l=ie.join(e,c);try{L.existsSync(l)&&L.rmSync(l,{recursive:!0,force:!0})}catch{}}try{L.existsSync(t)&&L.rmSync(t,{force:!0})}catch{}}async function Ro(e,t){let n=await fetch(e,{headers:{Accept:"application/octet-stream","User-Agent":"create-sailor"}});if(!n.ok)throw new Error(`Failed to download archive (${n.status})`);let o=Buffer.from(await n.arrayBuffer());if(o.byteLength<1024)throw new Error(`Downloaded archive is unexpectedly small (${o.byteLength} bytes)`);L.writeFileSync(t,o);let s=L.statSync(t);if(s.size!==o.byteLength)throw new Error(`Archive write verification failed (${s.size} != ${o.byteLength})`);return s.size}function ko(e,t){To("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function cn(e){try{let t=L.readdirSync(e);for(let n of t)L.rmSync(ie.join(e,n),{recursive:!0,force:!0})}catch{}}async function Vi(e,t){let n=L.mkdtempSync(ie.join(Ti.tmpdir(),"create-sailor-")),o=ie.join(n,"template.tar.gz");try{let s=await Bi(e.repo,e.ref);await Ro(Fi(e.repo,s),o),ko(o,t)}catch(s){if(!e.allowMutableFallback)throw s;cn(t),await Ro(Di(e.repo,e.ref),o),ko(o,t)}finally{L.rmSync(n,{recursive:!0,force:!0})}}async function Lo(e){L.mkdirSync(e,{recursive:!0});let t=Li();if(t){if(!L.existsSync(t))throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR does not exist: ${t}`);cn(e),Mi(t,e);try{xo(e)}catch(r){throw new Error(`Local template copied, but .templateignore processing failed: ${r instanceof Error?r.message:String(r)}`)}return}let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],s;for(let r of o){let i=Oi[r];try{if(await Vi(i,e),i.applyIgnore)try{xo(e)}catch(a){throw new Error(`Template cloned, but .templateignore processing failed: ${a instanceof Error?a.message:String(a)}`)}return}catch(a){s=a instanceof Error?a:new Error(String(a)),cn(e)}}throw new Error(`Failed to download the template from any source. Last error: ${s?.message??"unknown"}
1503
+ `}}function Ii(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),e.id==="aliyun-dm"&&(t["@alicloud/openapi-client"]="^0.4.12");let n={name:Le,version:"0.1.0",private:!0,description:`Transactional email via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
1504
+ `}async function vo(e,t,n){if(t==="none")return;let o=Eo(t);if(!o)throw new Error(`Unknown email provider "${t}". Valid ids: ${wt.map(i=>i.id).join(", ")}`);let r=Ne.join(e,"packages","email"),s=Ne.join(r,"src");Oe.existsSync(s)&&Oe.rmSync(s,{recursive:!0,force:!0}),an(Ne.join(r,"package.json"),Ii(o)),an(Ne.join(s,"types.ts"),hi),an(Ne.join(s,"index.ts"),Ai(o.id)),yi(e,Si(o))}import be from"fs";import bo from"path";function Ci(e,t){return new RegExp(`^\\s*${t}\\s*=`,"m").test(e)}function xi(e){return e.endsWith(`
1505
+ `)?e:`${e}
1506
+ `}async function _o(e,t){let n=bo.join(e,".env"),o=bo.join(e,".env.local"),r=be.existsSync(n)?be.readFileSync(n,"utf8"):"",s=be.existsSync(o)?be.readFileSync(o,"utf8"):"",i=`${r}
1507
+ ${s}`,a=[{name:"DATABASE_URL",value:String(t.databaseUrl)},{name:"NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY",value:String(t.clerkPublishable)},{name:"CLERK_SECRET_KEY",value:String(t.clerkSecret)},{name:"NEXT_PUBLIC_SITE_URL",value:"http://localhost:3000"}].filter(p=>!Ci(i,p.name)).map(p=>`${p.name}="${p.value}"`);if(a.length===0)return;let c=`# Automatically injected by create-sailor
1508
+ ${a.join(`
1509
+ `)}
1510
+ `;if(!be.existsSync(n)&&!be.existsSync(o))be.writeFileSync(o,c);else{let p=s?xi(s):"";be.writeFileSync(o,`${p}
1511
+ ${c}`)}}import wo from"crypto";import pt from"fs";import Po from"path";function Ue(e){return wo.randomBytes(e).toString("base64").replace(/=+$/,"")}function Ri(e){return wo.randomBytes(e).toString("hex")}function ki(){return{AUTH_SECRET:Ue(32),NEXTAUTH_SECRET:Ue(32),BETTER_AUTH_SECRET:Ue(32),JWT_SECRET:Ue(32),WEBHOOK_SECRET:Ri(16),ENCRYPTION_KEY:Ue(32),API_SECRET_KEY:Ue(32),SESSION_SECRET:Ue(32)}}function Ti(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Ni(e,t,n){let o=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=Ti(n);return e.replace(o,`${t}="${r}"`)}async function Ao(e){let t=Po.join(e,".env.example"),n=Po.join(e,".env.local");if(!pt.existsSync(t))return null;try{let o=pt.readFileSync(t,"utf8"),r=ki(),i=pt.existsSync(n)?pt.readFileSync(n,"utf8"):o;for(let a of Object.keys(r))i=Ni(i,a,r[a]);return pt.writeFileSync(n,i),r}catch(o){let r=o instanceof Error?o.message:String(o);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 Io(e){return At.find(t=>t.id===e)}var Ml=At.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Co(e,t,n="global"){let o=Io(t);if(!o)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${At.map(r=>r.id).join(", ")}`);if(o.id==="none"){z(e,"feature-flags");return}o.envVars.length>0&&oe(e,{category:"Feature Flags",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"FEATURE_FLAGS_PROVIDER",o.id)}import{execFileSync as To}from"child_process";import L from"fs";import Oi from"os";import ie from"path";import Li from"ignore";var Ui={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 Mi(){let e=process.env.SAILOR_TEMPLATE_LOCAL_DIR;if(!(!e||e.trim().length===0))return ie.resolve(e.trim())}var Di=new Set(["node_modules",".git","dist",".next",".turbo"]);function Fi(e,t){if(!L.statSync(e).isDirectory())throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR is not a directory: ${e}`);L.cpSync(e,t,{recursive:!0,dereference:!0,filter:o=>{let r=ie.basename(o);return!Di.has(r)}})}function ji(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function Bi(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function No(e){return/^[0-9a-f]{7,40}$/i.test(e)}function Vi(e,t){let n=`https://github.com/${e}.git`,o=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of o)try{let s=To("git",["ls-remote",n,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!s)continue;let[i]=s.split(/\s+/);if(No(i))return i}catch{}return null}async function Ki(e,t){if(No(t))return t;let n=await fetch(`https://api.github.com/repos/${e}/commits/${encodeURIComponent(t)}`,{headers:{Accept:"application/vnd.github+json","User-Agent":"create-sailor"}});if(!n.ok){let r=Vi(e,t);if(r)return r;throw new Error(`Failed to resolve ${e}@${t} (GitHub API ${n.status})`)}let o=await n.json();if(typeof o.sha!="string"||o.sha.length===0)throw new Error(`GitHub API did not return a commit SHA for ${e}@${t}`);return o.sha}function Oo(e,t,n){let o=L.readdirSync(t,{withFileTypes:!0});for(let r of o){if(r.name==="node_modules"||r.name===".git")continue;let s=ie.join(t,r.name),i=ie.relative(e,s).split(ie.sep).join("/");r.isDirectory()?(n.push(i+"/"),Oo(e,s,n)):n.push(i)}}function xo(e){let t=ie.join(e,".templateignore");if(!L.existsSync(t))return;let n=L.readFileSync(t,"utf8"),o=Li().add(n),r=[];Oo(e,e,r);let s=r.map(c=>c.endsWith("/")?c.slice(0,-1):c),i=new Set(o.filter(s)),a=s.filter(c=>!i.has(c)).sort((c,p)=>p.split("/").length-c.split("/").length);for(let c of a){let p=ie.join(e,c);try{L.existsSync(p)&&L.rmSync(p,{recursive:!0,force:!0})}catch{}}try{L.existsSync(t)&&L.rmSync(t,{force:!0})}catch{}}async function Ro(e,t){let n=await fetch(e,{headers:{Accept:"application/octet-stream","User-Agent":"create-sailor"}});if(!n.ok)throw new Error(`Failed to download archive (${n.status})`);let o=Buffer.from(await n.arrayBuffer());if(o.byteLength<1024)throw new Error(`Downloaded archive is unexpectedly small (${o.byteLength} bytes)`);L.writeFileSync(t,o);let r=L.statSync(t);if(r.size!==o.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${o.byteLength})`);return r.size}function ko(e,t){To("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function cn(e){try{let t=L.readdirSync(e);for(let n of t)L.rmSync(ie.join(e,n),{recursive:!0,force:!0})}catch{}}async function $i(e,t){let n=L.mkdtempSync(ie.join(Oi.tmpdir(),"create-sailor-")),o=ie.join(n,"template.tar.gz");try{let r=await Ki(e.repo,e.ref);await Ro(Bi(e.repo,r),o),ko(o,t)}catch(r){if(!e.allowMutableFallback)throw r;cn(t),await Ro(ji(e.repo,e.ref),o),ko(o,t)}finally{L.rmSync(n,{recursive:!0,force:!0})}}async function Lo(e){L.mkdirSync(e,{recursive:!0});let t=Mi();if(t){if(!L.existsSync(t))throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR does not exist: ${t}`);cn(e),Fi(t,e);try{xo(e)}catch(s){throw new Error(`Local template copied, but .templateignore processing failed: ${s instanceof Error?s.message:String(s)}`)}return}let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],r;for(let s of o){let i=Ui[s];try{if(await $i(i,e),i.applyIgnore)try{xo(e)}catch(a){throw new Error(`Template cloned, but .templateignore processing failed: ${a instanceof Error?a.message:String(a)}`)}return}catch(a){r=a instanceof Error?a:new Error(String(a)),cn(e)}}throw new Error(`Failed to download the template from any source. Last error: ${r?.message??"unknown"}
1513
1512
 
1514
1513
  Ensure you have internet access and 'tar' installed.
1515
- You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import It from"fs";import pn from"path";var Ki="node scripts/governance/lint-no-raw-inputs.mjs",$i="node scripts/governance/lint-repository-seam.mjs",Yi="node scripts/governance/lint-brand-literals.mjs",qi="node scripts/governance/lint-microcopy.mjs",Gi=/\bnode\s+scripts\/(governance\/)?lint-[\w-]+\.mjs/g,Hi=/\bnode\s+scripts\/lint-[\w-]+\.mjs/,Wi={scanRoots:["apps"],primitivesImport:"@nebutra/ui/primitives",whitelist:["/storybook/src/stories/","/design-docs/src/components/previews/","/sailor-docs/src/components/previews/","\\.test\\.tsx?$","/__tests__/"]},Xi={coreDomains:["^packages/.*/(billing|license|metering|auth|audit|permissions|identity|tenant)/","^backends/gateway/src/routes/(billing|ai|admin|legal|integrations|webhooks)/","^apps/web/src/app/api/"],seamPaths:["^packages/platform/repositories/","^packages/platform/db/"],dbAccessors:["getTenantDb","getSystemDb"],allowlist:["apps/web/src/app/api/invitations/[invitationId]/accept/route.ts","apps/web/src/app/api/onboarding/invite-members/route.ts","apps/web/src/app/api/startup-os/projects/[projectId]/runs/[runId]/execute/route.ts","apps/web/src/app/api/cofounder/room/[profileId]/form-team/route.ts","apps/web/src/app/api/provider-keys/route.ts","backends/gateway/src/routes/admin/index.ts","backends/gateway/src/routes/ai/api-keys.ts","backends/gateway/src/routes/ai/usage.ts","backends/gateway/src/routes/billing/index.ts","backends/gateway/src/routes/integrations/index.ts","backends/gateway/src/routes/legal/consent.ts","backends/gateway/src/routes/webhooks/clerk.ts","backends/gateway/src/routes/webhooks/stripe.ts","packages/commerce/license/src/issue-license.ts","packages/commerce/license/src/validate-license.ts","packages/commerce/billing/src/credits/service.ts","packages/commerce/billing/src/usage/ledger.ts","packages/iam/audit/src/index.ts","packages/iam/auth/src/plugins/passkey-plugin.ts"]},zi={scanRoots:["apps/web/src"],excludePaths:["/api/","\\.test\\.tsx?$","/__tests__/","/storybook/src/stories/","/design-docs/","/sailor-docs/"],bannedPatterns:[],allowlist:[]},Uo={governedPaths:["apps","packages/commerce","packages/integrations/email"],allowExpressions:["Nebutra","\u4E91\u6BD3\u667A\u80FD","\u4E91\u6BD3","nebutra\\.com","nebutra\\.ai","#0033FE","#0BF1C3"],knownExemptPatterns:["\\.stories\\.tsx?$","/__tests__/","\\.test\\.tsx?$","/previews/","^packages/design/brand/","^packages/design/tokens/","^packages/design/design-tokens/"],allowlist:[]},Ji=["apps/design-docs/mdx-components.tsx","apps/design-docs/next.config.ts","apps/design-docs/src/__registry__/index.tsx","apps/design-docs/src/app/[lang]/docs/[[...slug]]/page.tsx","apps/design-docs/src/app/[lang]/docs/layout.tsx","apps/design-docs/src/app/[lang]/layout.tsx","apps/design-docs/src/app/[lang]/registry/[name]/page.tsx","apps/design-docs/src/app/[lang]/registry/page.tsx","apps/design-docs/src/app/og/docs/[...slug]/route.tsx","apps/design-docs/src/components/brand-overview-visuals.tsx","apps/design-docs/src/components/color-usage.tsx","apps/design-docs/src/components/component-preview.tsx","apps/design-docs/src/components/gradient-demos.tsx","apps/design-docs/src/components/introduction-hero.tsx","apps/design-docs/src/components/motion-demos.tsx","apps/design-docs/src/components/pattern-demos.tsx","apps/design-docs/src/components/registry/registry-card.tsx","apps/design-docs/src/lib/github.ts","apps/design-docs/src/lib/registry-strings.ts","apps/design-docs/src/lib/registry.ts","apps/idp/src/app/layout.tsx","apps/idp/src/app/oauth/authorize/page.tsx","apps/idp/src/app/page.tsx","apps/idp/src/lib/oidc.ts","apps/landing-page/src/app/[lang]/layout.tsx","apps/landing-page/src/app/api/blog/comments/route.ts","apps/landing-page/src/app/api/blog/reactions/route.ts","apps/landing-page/src/app/api/og/route.ts","apps/landing-page/src/app/apple-icon.tsx","apps/landing-page/src/components/auth/google-one-tap.tsx","apps/landing-page/src/components/cookie-consent-banner.tsx","apps/landing-page/src/components/marketing/ProductHuntSection.tsx","apps/landing-page/src/components/marketing/TestimonialsSection.tsx","apps/landing-page/src/i18n/request.ts","apps/landing-page/src/lib/analytics/emit.ts","apps/landing-page/src/lib/blog-fallback.ts","apps/landing-page/src/lib/constants/playbook-data.ts","apps/landing-page/src/lib/constants/resources-data.ts","apps/landing-page/src/lib/constants/solutions-data.ts","apps/landing-page/src/lib/docs-links.ts","apps/landing-page/src/lib/env.ts","apps/landing-page/src/lib/landing-content.ts","apps/landing-page/src/lib/seo/metadata.ts","apps/landing-page/src/lib/seo/site-routes.ts","apps/landing-page/src/lib/status-checks.ts","apps/landing-page/src/proxy.ts","apps/mail-preview/scripts/export.ts","apps/mail-preview/scripts/render-react-templates.ts","apps/mail-preview/src/app/api/send-test/route.ts","apps/mail-preview/src/app/layout.tsx","apps/mail-preview/src/lib/fixtures.ts","apps/web/next.config.ts","apps/web/src/app/(app)/checkout-return/page.tsx","apps/web/src/app/(app)/choose-plan/page.tsx","apps/web/src/app/(app)/settings/api-keys/page.tsx","apps/web/src/app/(app)/settings/notifications/page.tsx","apps/web/src/app/(app)/settings/provider-keys/page.tsx","apps/web/src/app/(auth)/desktop-auth/complete/page.tsx","apps/web/src/app/(public)/page.tsx","apps/web/src/app/[locale]/welcome/page.tsx","apps/web/src/app/api/account/email-change/route.ts","apps/web/src/app/api/admin/access-invites/route.ts","apps/web/src/app/api/blog/comments/route.ts","apps/web/src/app/api/blog/reactions/route.ts","apps/web/src/app/api/me/public/route.ts","apps/web/src/app/api/organizations/[orgId]/members/route.ts","apps/web/src/app/global-error.tsx","apps/web/src/components/ErrorBoundary.tsx","apps/web/src/components/api-keys/create-api-key-dialog.tsx","apps/web/src/components/appearance/store.ts","apps/web/src/components/auth/auth-banner.tsx","apps/web/src/components/auth/desktop-auth-complete-handoff.tsx","apps/web/src/components/auth/sign-up-form.tsx","apps/web/src/components/billing/billing-self-service.tsx","apps/web/src/components/navigation/public-page-chrome.tsx","apps/web/src/components/notifications/inbox-bell.tsx","apps/web/src/components/notifications/notification-inbox-preview.tsx","apps/web/src/components/notifications/notification-preference-matrix.tsx","apps/web/src/components/notifications/notification-runtime-banner.tsx","apps/web/src/components/settings/security/security-capabilities.ts","apps/web/src/components/settings/security/security-settings-client.tsx","apps/web/src/components/theme-playground/design-md-import.tsx","apps/web/src/components/theme-playground/theme-playground-workbench.tsx","apps/web/src/components/theme-playground/theme-token-data.ts","apps/web/src/lib/api.ts","apps/web/src/lib/api/client.ts","apps/web/src/lib/env.ts","apps/web/src/lib/integrations/catalog.tsx","apps/web/src/lib/permissions.ts","apps/web/src/lib/public-url-defaults.ts","apps/web/src/lib/session-hint.ts","apps/web/src/lib/startup-os/company-context/generate.ts","apps/web/src/lib/startup-os/company-context/projection.ts","apps/web/src/lib/startup-os/conversation.ts","apps/web/src/lib/startup-os/execution.ts","apps/web/src/lib/startup-os/files.ts","apps/web/src/proxy.ts","packages/commerce/billing/src/index.ts","packages/commerce/contracts/src/identity.ts","packages/commerce/legal/src/components/CookieBanner.tsx","packages/commerce/legal/src/documents/config.ts","packages/commerce/legal/src/index.ts","packages/commerce/marketing/src/components/ProductHuntBadge.tsx","packages/commerce/marketing/src/config/index.ts","packages/commerce/marketing/src/index.ts","packages/integrations/email/src/index.ts","packages/integrations/email/src/templates/_layout.ts","packages/integrations/email/src/templates/invitation.tsx"];function Qi(e,t){let n=(e??"").replace(Gi,"").split("&&").map(s=>s.trim()).filter(Boolean).join(" && ");return[n.length>0?n:"biome check .",...t].join(" && ")}function Zi(e){let t=new RegExp(Uo.allowExpressions.join("|"));return Ji.filter(n=>{try{return t.test(It.readFileSync(pn.join(e,n),"utf8"))}catch{return!1}})}async function Mo(e,t){let n=t.database!=="none",o=[Ki];n&&o.push($i),o.push(Yi),o.push(qi);let s={...Uo,allowlist:Zi(e)},r={rawInputs:Wi,brandLiterals:s,microcopyRules:zi};n&&(r.repositorySeam=Xi);let i=pn.join(e,"governance.config.json");It.writeFileSync(i,JSON.stringify(r,null,2)+`
1516
- `);let a=pn.join(e,"package.json"),c;try{c=It.readFileSync(a,"utf8")}catch(l){if(l.code!=="ENOENT")throw l}if(c!==void 0){let l=JSON.parse(c);l.scripts=l.scripts??{};for(let[u,d]of Object.entries(l.scripts))u!=="lint"&&typeof d=="string"&&Hi.test(d)&&delete l.scripts[u];l.scripts.lint=Qi(l.scripts.lint,o),It.writeFileSync(a,JSON.stringify(l,null,2)+`
1517
- `)}return{lints:o,configWritten:!0}}import{createHmac as ta,randomBytes as na}from"crypto";import Q from"fs";import ae from"path";import{fileURLToPath as oa}from"url";var ea=[{id:"v1",key:"nebutra-sailor:scaffold-marker:v1"}];function Do(){let e=ea[0];if(!e)throw new Error("license-signing-keys: registry is empty \u2014 at least one key is required.");return e}var sa=oa(import.meta.url),Fo=ae.dirname(sa),jo="scaffold-meta.json",Bo=".nebutra";function ra(e){if(e)return e;let t=[ae.join(Fo,"..","templates"),ae.join(Fo,"..","..","templates")];for(let n of t)if(Q.existsSync(n))return n;return t[0]}function ia(e,t){let n=`${e.cliVersion}|${e.scaffoldedAt}|${e.projectName}|${e.nonce}`;return ta("sha256",t).update(n).digest("hex")}function Vo(e,t){let n=[],o=ra(t.templatesRoot),s=ae.join(e,"LICENSE");if(Q.existsSync(s)){let h=Q.readFileSync(s,"utf-8").slice(0,256);/GNU AFFERO GENERAL PUBLIC LICENSE/i.test(h)&&(Q.renameSync(s,ae.join(e,"LICENSE-AGPL-REFERENCE.md")),n.push("LICENSE-AGPL-REFERENCE.md (preserved upstream AGPL)"))}let r=ae.join(o,"LICENSE-INDEPENDENT.md");if(!Q.existsSync(r))throw new Error(`LICENSE-INDEPENDENT.md template missing at ${r}; cannot emit license.`);Q.copyFileSync(r,ae.join(e,"LICENSE")),n.push("LICENSE");let i=new Date().toISOString(),a=na(12).toString("hex"),c=Do(),l=ia({cliVersion:t.cliVersion,scaffoldedAt:i,projectName:t.projectName,nonce:a},c.key),u={schemaVersion:1,cliVersion:t.cliVersion,scaffoldedAt:i,projectName:t.projectName,nonce:a,signature:l,signingKeyId:c.id,purpose:"Marks this project as scaffolded by the official `create-sailor` CLI. The Independent Developer License in LICENSE applies as long as this file is present and the signature verifies.",license:{tier:"independent",file:"LICENSE",upgradeUrl:"https://nebutra.com/get-license"}},d=ae.join(e,Bo);Q.mkdirSync(d,{recursive:!0}),Q.writeFileSync(ae.join(d,jo),`${JSON.stringify(u,null,2)}
1514
+ You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import It from"fs";import pn from"path";var Yi="node scripts/governance/lint-no-raw-inputs.mjs",qi="node scripts/governance/lint-repository-seam.mjs",Gi="node scripts/governance/lint-brand-literals.mjs",Hi="node scripts/governance/lint-microcopy.mjs",Wi=/\bnode\s+scripts\/(governance\/)?lint-[\w-]+\.mjs/g,Xi=/\bnode\s+scripts\/lint-[\w-]+\.mjs/,zi={scanRoots:["apps"],primitivesImport:"@nebutra/ui/primitives",whitelist:["/storybook/src/stories/","/design-docs/src/components/previews/","/sailor-docs/src/components/previews/","\\.test\\.tsx?$","/__tests__/"]},Ji={coreDomains:["^packages/.*/(billing|license|metering|auth|audit|permissions|identity|tenant)/","^backends/gateway/src/routes/(billing|ai|admin|legal|integrations|webhooks)/","^apps/web/src/app/api/"],seamPaths:["^packages/platform/repositories/","^packages/platform/db/"],dbAccessors:["getTenantDb","getSystemDb"],allowlist:["apps/web/src/app/api/invitations/[invitationId]/accept/route.ts","apps/web/src/app/api/onboarding/invite-members/route.ts","apps/web/src/app/api/startup-os/projects/[projectId]/runs/[runId]/execute/route.ts","apps/web/src/app/api/cofounder/room/[profileId]/form-team/route.ts","apps/web/src/app/api/provider-keys/route.ts","backends/gateway/src/routes/admin/index.ts","backends/gateway/src/routes/ai/api-keys.ts","backends/gateway/src/routes/ai/usage.ts","backends/gateway/src/routes/billing/index.ts","backends/gateway/src/routes/integrations/index.ts","backends/gateway/src/routes/legal/consent.ts","backends/gateway/src/routes/webhooks/clerk.ts","backends/gateway/src/routes/webhooks/stripe.ts","packages/commerce/license/src/issue-license.ts","packages/commerce/license/src/validate-license.ts","packages/commerce/billing/src/credits/service.ts","packages/commerce/billing/src/usage/ledger.ts","packages/iam/audit/src/index.ts","packages/iam/auth/src/plugins/passkey-plugin.ts"]},Qi={scanRoots:["apps/web/src"],excludePaths:["/api/","\\.test\\.tsx?$","/__tests__/","/storybook/src/stories/","/design-docs/","/sailor-docs/"],bannedPatterns:[],allowlist:[]},Uo={governedPaths:["apps","packages/commerce","packages/integrations/email"],allowExpressions:["Nebutra","\u4E91\u6BD3\u667A\u80FD","\u4E91\u6BD3","nebutra\\.com","nebutra\\.ai","#0033FE","#0BF1C3"],knownExemptPatterns:["\\.stories\\.tsx?$","/__tests__/","\\.test\\.tsx?$","/previews/","^packages/design/brand/","^packages/design/tokens/","^packages/design/design-tokens/"],allowlist:[]},Zi=["apps/design-docs/mdx-components.tsx","apps/design-docs/next.config.ts","apps/design-docs/src/__registry__/index.tsx","apps/design-docs/src/app/[lang]/docs/[[...slug]]/page.tsx","apps/design-docs/src/app/[lang]/docs/layout.tsx","apps/design-docs/src/app/[lang]/layout.tsx","apps/design-docs/src/app/[lang]/registry/[name]/page.tsx","apps/design-docs/src/app/[lang]/registry/page.tsx","apps/design-docs/src/app/og/docs/[...slug]/route.tsx","apps/design-docs/src/components/brand-overview-visuals.tsx","apps/design-docs/src/components/color-usage.tsx","apps/design-docs/src/components/component-preview.tsx","apps/design-docs/src/components/gradient-demos.tsx","apps/design-docs/src/components/introduction-hero.tsx","apps/design-docs/src/components/motion-demos.tsx","apps/design-docs/src/components/pattern-demos.tsx","apps/design-docs/src/components/registry/registry-card.tsx","apps/design-docs/src/lib/github.ts","apps/design-docs/src/lib/registry-strings.ts","apps/design-docs/src/lib/registry.ts","apps/idp/src/app/layout.tsx","apps/idp/src/app/oauth/authorize/page.tsx","apps/idp/src/app/page.tsx","apps/idp/src/lib/oidc.ts","apps/landing-page/src/app/[lang]/layout.tsx","apps/landing-page/src/app/api/blog/comments/route.ts","apps/landing-page/src/app/api/blog/reactions/route.ts","apps/landing-page/src/app/api/og/route.ts","apps/landing-page/src/app/apple-icon.tsx","apps/landing-page/src/components/auth/google-one-tap.tsx","apps/landing-page/src/components/cookie-consent-banner.tsx","apps/landing-page/src/components/marketing/ProductHuntSection.tsx","apps/landing-page/src/components/marketing/TestimonialsSection.tsx","apps/landing-page/src/i18n/request.ts","apps/landing-page/src/lib/analytics/emit.ts","apps/landing-page/src/lib/blog-fallback.ts","apps/landing-page/src/lib/constants/playbook-data.ts","apps/landing-page/src/lib/constants/resources-data.ts","apps/landing-page/src/lib/constants/solutions-data.ts","apps/landing-page/src/lib/docs-links.ts","apps/landing-page/src/lib/env.ts","apps/landing-page/src/lib/landing-content.ts","apps/landing-page/src/lib/seo/metadata.ts","apps/landing-page/src/lib/seo/site-routes.ts","apps/landing-page/src/lib/status-checks.ts","apps/landing-page/src/proxy.ts","apps/mail-preview/scripts/export.ts","apps/mail-preview/scripts/render-react-templates.ts","apps/mail-preview/src/app/api/send-test/route.ts","apps/mail-preview/src/app/layout.tsx","apps/mail-preview/src/lib/fixtures.ts","apps/web/next.config.ts","apps/web/src/app/(app)/checkout-return/page.tsx","apps/web/src/app/(app)/choose-plan/page.tsx","apps/web/src/app/(app)/settings/api-keys/page.tsx","apps/web/src/app/(app)/settings/notifications/page.tsx","apps/web/src/app/(app)/settings/provider-keys/page.tsx","apps/web/src/app/(auth)/desktop-auth/complete/page.tsx","apps/web/src/app/(public)/page.tsx","apps/web/src/app/[locale]/welcome/page.tsx","apps/web/src/app/api/account/email-change/route.ts","apps/web/src/app/api/admin/access-invites/route.ts","apps/web/src/app/api/blog/comments/route.ts","apps/web/src/app/api/blog/reactions/route.ts","apps/web/src/app/api/me/public/route.ts","apps/web/src/app/api/organizations/[orgId]/members/route.ts","apps/web/src/app/global-error.tsx","apps/web/src/components/ErrorBoundary.tsx","apps/web/src/components/api-keys/create-api-key-dialog.tsx","apps/web/src/components/appearance/store.ts","apps/web/src/components/auth/auth-banner.tsx","apps/web/src/components/auth/desktop-auth-complete-handoff.tsx","apps/web/src/components/auth/sign-up-form.tsx","apps/web/src/components/billing/billing-self-service.tsx","apps/web/src/components/navigation/public-page-chrome.tsx","apps/web/src/components/notifications/inbox-bell.tsx","apps/web/src/components/notifications/notification-inbox-preview.tsx","apps/web/src/components/notifications/notification-preference-matrix.tsx","apps/web/src/components/notifications/notification-runtime-banner.tsx","apps/web/src/components/settings/security/security-capabilities.ts","apps/web/src/components/settings/security/security-settings-client.tsx","apps/web/src/components/theme-playground/design-md-import.tsx","apps/web/src/components/theme-playground/theme-playground-workbench.tsx","apps/web/src/components/theme-playground/theme-token-data.ts","apps/web/src/lib/api.ts","apps/web/src/lib/api/client.ts","apps/web/src/lib/env.ts","apps/web/src/lib/integrations/catalog.tsx","apps/web/src/lib/permissions.ts","apps/web/src/lib/public-url-defaults.ts","apps/web/src/lib/session-hint.ts","apps/web/src/lib/startup-os/company-context/generate.ts","apps/web/src/lib/startup-os/company-context/projection.ts","apps/web/src/lib/startup-os/conversation.ts","apps/web/src/lib/startup-os/execution.ts","apps/web/src/lib/startup-os/files.ts","apps/web/src/proxy.ts","packages/commerce/billing/src/index.ts","packages/commerce/contracts/src/identity.ts","packages/commerce/legal/src/components/CookieBanner.tsx","packages/commerce/legal/src/documents/config.ts","packages/commerce/legal/src/index.ts","packages/commerce/marketing/src/components/ProductHuntBadge.tsx","packages/commerce/marketing/src/config/index.ts","packages/commerce/marketing/src/index.ts","packages/integrations/email/src/index.ts","packages/integrations/email/src/templates/_layout.ts","packages/integrations/email/src/templates/invitation.tsx"];function ea(e,t){let n=(e??"").replace(Wi,"").split("&&").map(r=>r.trim()).filter(Boolean).join(" && ");return[n.length>0?n:"biome check .",...t].join(" && ")}function ta(e){let t=new RegExp(Uo.allowExpressions.join("|"));return Zi.filter(n=>{try{return t.test(It.readFileSync(pn.join(e,n),"utf8"))}catch{return!1}})}async function Mo(e,t){let n=t.database!=="none",o=[Yi];n&&o.push(qi),o.push(Gi),o.push(Hi);let r={...Uo,allowlist:ta(e)},s={rawInputs:zi,brandLiterals:r,microcopyRules:Qi};n&&(s.repositorySeam=Ji);let i=pn.join(e,"governance.config.json");It.writeFileSync(i,JSON.stringify(s,null,2)+`
1515
+ `);let a=pn.join(e,"package.json"),c;try{c=It.readFileSync(a,"utf8")}catch(p){if(p.code!=="ENOENT")throw p}if(c!==void 0){let p=JSON.parse(c);p.scripts=p.scripts??{};for(let[u,d]of Object.entries(p.scripts))u!=="lint"&&typeof d=="string"&&Xi.test(d)&&delete p.scripts[u];p.scripts.lint=ea(p.scripts.lint,o),It.writeFileSync(a,JSON.stringify(p,null,2)+`
1516
+ `)}return{lints:o,configWritten:!0}}import{createHmac as oa,randomBytes as ra}from"crypto";import Q from"fs";import ae from"path";import{fileURLToPath as sa}from"url";var na=[{id:"v1",key:"nebutra-sailor:scaffold-marker:v1"}];function Do(){let e=na[0];if(!e)throw new Error("license-signing-keys: registry is empty \u2014 at least one key is required.");return e}var ia=sa(import.meta.url),Fo=ae.dirname(ia),jo="scaffold-meta.json",Bo=".nebutra";function aa(e){if(e)return e;let t=[ae.join(Fo,"..","templates"),ae.join(Fo,"..","..","templates")];for(let n of t)if(Q.existsSync(n))return n;return t[0]}function ca(e,t){let n=`${e.cliVersion}|${e.scaffoldedAt}|${e.projectName}|${e.nonce}`;return oa("sha256",t).update(n).digest("hex")}function Vo(e,t){let n=[],o=aa(t.templatesRoot),r=ae.join(e,"LICENSE");if(Q.existsSync(r)){let h=Q.readFileSync(r,"utf-8").slice(0,256);/GNU AFFERO GENERAL PUBLIC LICENSE/i.test(h)&&(Q.renameSync(r,ae.join(e,"LICENSE-AGPL-REFERENCE.md")),n.push("LICENSE-AGPL-REFERENCE.md (preserved upstream AGPL)"))}let s=ae.join(o,"LICENSE-INDEPENDENT.md");if(!Q.existsSync(s))throw new Error(`LICENSE-INDEPENDENT.md template missing at ${s}; cannot emit license.`);Q.copyFileSync(s,ae.join(e,"LICENSE")),n.push("LICENSE");let i=new Date().toISOString(),a=ra(12).toString("hex"),c=Do(),p=ca({cliVersion:t.cliVersion,scaffoldedAt:i,projectName:t.projectName,nonce:a},c.key),u={schemaVersion:1,cliVersion:t.cliVersion,scaffoldedAt:i,projectName:t.projectName,nonce:a,signature:p,signingKeyId:c.id,purpose:"Marks this project as scaffolded by the official `create-sailor` CLI. The Independent Developer License in LICENSE applies as long as this file is present and the signature verifies.",license:{tier:"independent",file:"LICENSE",upgradeUrl:"https://nebutra.com/get-license"}},d=ae.join(e,Bo);Q.mkdirSync(d,{recursive:!0}),Q.writeFileSync(ae.join(d,jo),`${JSON.stringify(u,null,2)}
1518
1517
  `),n.push(`${Bo}/${jo}`);let _=ae.join(e,"README.md");if(Q.existsSync(_)){let h=Q.readFileSync(_,"utf-8");h.includes("Nebutra-Sailor Independent Developer License")||(Q.writeFileSync(_,`> **License notice:** scaffolded by \`create-sailor\` under the
1519
1518
  > [Nebutra-Sailor Independent Developer License](./LICENSE). Free for
1520
1519
  > individuals/OPC with \u2264 1 FTE and < $1M ARR; upgrade for larger teams at
1521
1520
  > https://nebutra.com/get-license. The upstream repository remains
1522
1521
  > AGPL-3.0 \u2014 see \`LICENSE-AGPL-REFERENCE.md\`.
1523
1522
 
1524
- `+h),n.push("README.md (prepended license notice)"))}return{wrote:n}}import Ue from"fs";import ln from"path";async function Ko(e,t){let n=ln.join(e,"packages","mcp");if(t==="off"){Ue.existsSync(n)&&Ue.rmSync(n,{recursive:!0,force:!0});let s=ln.join(e,"packages","cli","src","commands","mcp-server.ts");Ue.existsSync(s)&&Ue.rmSync(s,{force:!0});return}let o=ln.join(e,".env.example");if(Ue.existsSync(o)){let s=Ue.readFileSync(o,"utf-8"),r="# MCP Server (Agent-friendly API)";if(!s.includes(r)){let i=["","# =============================================",r,"# 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(`
1525
- `);Ue.appendFileSync(o,i)}}}import pt from"fs";import $o from"path";async function Yo(e,t,n){let o=$o.join(e,"packages","metering"),s;if(t==="auto"?s=n!=="none"?"on":"off":t==="on"||t==="off"?s=t:s="off",s==="off"){pt.existsSync(o)&&pt.rmSync(o,{recursive:!0,force:!0});return}let r=$o.join(e,".env.example");if(!pt.existsSync(r))return;let i=pt.readFileSync(r,"utf-8"),a="# Metering (usage-based billing)";if(!i.includes(a)){let c=["","# =============================================",a,"# 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(`
1526
- `);pt.appendFileSync(r,c)}}import de from"fs";import D from"path";var qo=[{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:""}],cd=qo.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Go(e){return qo.find(t=>t.id===e)}var dn={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 aa(e){de.mkdirSync(e,{recursive:!0})}function un(e,t){let n=D.join(e,"package.json");if(!de.existsSync(n))return;let o;try{o=JSON.parse(de.readFileSync(n,"utf-8"))}catch(a){console.error(`Failed to parse ${n}:`,a);return}let r={...o.dependencies??{}};for(let[a,c]of Object.entries(t))r[a]||(r[a]=c);let i={...o,dependencies:r};de.writeFileSync(n,JSON.stringify(i,null,2)+`
1527
- `)}function ce(e,t){aa(D.dirname(e)),de.writeFileSync(e,t)}function lt(e,t){let n=D.join(e,".env.example");de.existsSync(n)?de.appendFileSync(n,`
1528
- `+t):de.writeFileSync(n,t)}function ca(e){let t=`import * as Sentry from "@sentry/nextjs";
1523
+ `+h),n.push("README.md (prepended license notice)"))}return{wrote:n}}import Me from"fs";import ln from"path";async function Ko(e,t){let n=ln.join(e,"packages","mcp");if(t==="off"){Me.existsSync(n)&&Me.rmSync(n,{recursive:!0,force:!0});let r=ln.join(e,"packages","cli","src","commands","mcp-server.ts");Me.existsSync(r)&&Me.rmSync(r,{force:!0});return}let o=ln.join(e,".env.example");if(Me.existsSync(o)){let r=Me.readFileSync(o,"utf-8"),s="# MCP Server (Agent-friendly API)";if(!r.includes(s)){let i=["","# =============================================",s,"# Docs: https://modelcontextprotocol.io","# =============================================","# MCP server exposes your SaaS capabilities to AI agents via MCP protocol.","# Run: pnpm mcp-server (starts stdio server)","# No config required for stdio transport. HTTP transport needs:",'MCP_HTTP_PORT="3100"','MCP_API_KEY=""',""].join(`
1524
+ `);Me.appendFileSync(o,i)}}}import lt from"fs";import $o from"path";async function Yo(e,t,n){let o=$o.join(e,"packages","metering"),r;if(t==="auto"?r=n!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){lt.existsSync(o)&&lt.rmSync(o,{recursive:!0,force:!0});return}let s=$o.join(e,".env.example");if(!lt.existsSync(s))return;let i=lt.readFileSync(s,"utf-8"),a="# Metering (usage-based billing)";if(!i.includes(a)){let c=["","# =============================================",a,"# 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(`
1525
+ `);lt.appendFileSync(s,c)}}import de from"fs";import D from"path";var qo=[{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:""}],ld=qo.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Go(e){return qo.find(t=>t.id===e)}var dn={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 pa(e){de.mkdirSync(e,{recursive:!0})}function un(e,t){let n=D.join(e,"package.json");if(!de.existsSync(n))return;let o;try{o=JSON.parse(de.readFileSync(n,"utf-8"))}catch(a){console.error(`Failed to parse ${n}:`,a);return}let s={...o.dependencies??{}};for(let[a,c]of Object.entries(t))s[a]||(s[a]=c);let i={...o,dependencies:s};de.writeFileSync(n,JSON.stringify(i,null,2)+`
1526
+ `)}function ce(e,t){pa(D.dirname(e)),de.writeFileSync(e,t)}function dt(e,t){let n=D.join(e,".env.example");de.existsSync(n)?de.appendFileSync(n,`
1527
+ `+t):de.writeFileSync(n,t)}function la(e){let t=`import * as Sentry from "@sentry/nextjs";
1529
1528
 
1530
1529
  Sentry.init({
1531
1530
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
@@ -1554,7 +1553,7 @@ Sentry.init({
1554
1553
  tracesSampleRate: 1.0,
1555
1554
  environment: process.env.NODE_ENV,
1556
1555
  });
1557
- `,s=`/**
1556
+ `,r=`/**
1558
1557
  * Next.js instrumentation hook \u2014 wires Sentry into Node and Edge runtimes.
1559
1558
  * See https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation
1560
1559
  */
@@ -1568,14 +1567,14 @@ export async function register() {
1568
1567
  }
1569
1568
 
1570
1569
  export { captureRequestError as onRequestError } from "@sentry/nextjs";
1571
- `;ce(D.join(e,"sentry.client.config.ts"),t),ce(D.join(e,"sentry.server.config.ts"),n),ce(D.join(e,"sentry.edge.config.ts"),o),ce(D.join(e,"instrumentation.ts"),s)}function pa(){return`# Sentry \u2014 error tracking + performance monitoring
1570
+ `;ce(D.join(e,"sentry.client.config.ts"),t),ce(D.join(e,"sentry.server.config.ts"),n),ce(D.join(e,"sentry.edge.config.ts"),o),ce(D.join(e,"instrumentation.ts"),r)}function da(){return`# Sentry \u2014 error tracking + performance monitoring
1572
1571
  # Get your DSN from https://sentry.io/settings/projects/<project>/keys/
1573
1572
  SENTRY_DSN=
1574
1573
  NEXT_PUBLIC_SENTRY_DSN=
1575
1574
  SENTRY_ORG=
1576
1575
  SENTRY_PROJECT=
1577
1576
  SENTRY_AUTH_TOKEN=
1578
- `}function la(e){let t=`/**
1577
+ `}function ua(e){let t=`/**
1579
1578
  * Next.js instrumentation hook \u2014 wires Datadog APM (dd-trace) into Node runtime.
1580
1579
  * Edge runtime is not supported by dd-trace; only nodejs is initialized.
1581
1580
  */
@@ -1623,7 +1622,7 @@ export function initDatadogRum(): void {
1623
1622
  });
1624
1623
  initialized = true;
1625
1624
  }
1626
- `;ce(D.join(e,"instrumentation.ts"),t),ce(D.join(e,"src","lib","monitoring","datadog-rum.ts"),n)}function da(){return`# Datadog \u2014 APM + RUM
1625
+ `;ce(D.join(e,"instrumentation.ts"),t),ce(D.join(e,"src","lib","monitoring","datadog-rum.ts"),n)}function ma(){return`# Datadog \u2014 APM + RUM
1627
1626
  # Server APM (dd-trace)
1628
1627
  DD_API_KEY=
1629
1628
  DD_APP_KEY=
@@ -1638,7 +1637,7 @@ NEXT_PUBLIC_DD_SITE=datadoghq.com
1638
1637
  NEXT_PUBLIC_DD_SERVICE=sailor-web
1639
1638
  NEXT_PUBLIC_DD_ENV=production
1640
1639
  NEXT_PUBLIC_DD_VERSION=
1641
- `}function ua(e){let t=`/**
1640
+ `}function ga(e){let t=`/**
1642
1641
  * Bugsnag server-side initialization.
1643
1642
  * Import this once at the top of your server entrypoint or a shared init module.
1644
1643
  */
@@ -1687,11 +1686,11 @@ export function getBugsnagErrorBoundary() {
1687
1686
  errorBoundary = plugin.createErrorBoundary(React) as typeof errorBoundary;
1688
1687
  return errorBoundary;
1689
1688
  }
1690
- `;ce(D.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),ce(D.join(e,"src","lib","monitoring","bugsnag.client.tsx"),n)}function ma(){return`# Bugsnag \u2014 error tracking
1689
+ `;ce(D.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),ce(D.join(e,"src","lib","monitoring","bugsnag.client.tsx"),n)}function fa(){return`# Bugsnag \u2014 error tracking
1691
1690
  BUGSNAG_API_KEY=
1692
1691
  NEXT_PUBLIC_BUGSNAG_API_KEY=
1693
1692
  APP_VERSION=
1694
- `}function ga(e){ce(D.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1693
+ `}function ya(e){ce(D.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1695
1694
  /**
1696
1695
  * \u963F\u91CC\u4E91 ARMS (Application Real-time Monitoring Service) browser agent.
1697
1696
  * Injects the official JS agent via next/script.
@@ -1712,11 +1711,11 @@ export function ArmsScript() {
1712
1711
  />
1713
1712
  );
1714
1713
  }
1715
- `)}function fa(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1714
+ `)}function Sa(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1716
1715
  ALIYUN_ARMS_LICENSE_KEY=
1717
1716
  ALIYUN_ARMS_APP_NAME=
1718
1717
  NEXT_PUBLIC_ARMS_PID=
1719
- `}function ya(e){ce(D.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1718
+ `}function ha(e){ce(D.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1720
1719
  /**
1721
1720
  * \u542C\u4E91 Browser Agent (\u524D\u7AEF\u6027\u80FD\u76D1\u63A7).
1722
1721
  * Docs: https://www.tingyun.com/docs
@@ -1734,12 +1733,12 @@ export function TingYunScript() {
1734
1733
  />
1735
1734
  );
1736
1735
  }
1737
- `)}function Sa(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1736
+ `)}function Ea(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1738
1737
  TINGYUN_LICENSE_KEY=
1739
1738
  NEXT_PUBLIC_TINGYUN_APP_KEY=
1740
- `}async function Ho(e,t,n="global"){let o=Go(t);if(!o||o.id==="none")return;let s=D.join(e,"apps","web");if(!de.existsSync(s))return;let r=o.id;try{switch(r){case"sentry":ca(s),un(s,dn.sentry),lt(e,pa());return;case"datadog":la(s),un(s,dn.datadog),lt(e,da());return;case"bugsnag":ua(s),un(s,dn.bugsnag),lt(e,ma());return;case"aliyun-arms":ga(s),lt(e,fa());return;case"tingyun":ya(s),lt(e,Sa());return;default:return}}catch(i){throw console.error(`Failed to apply monitoring selection "${t}":`,i),new Error(`Monitoring scaffold for "${t}" failed \u2014 see stderr for details.`)}}var 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 Wo(e){return Ct.find(t=>t.id===e)}var gd=Ct.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Xo(e,t,n="global"){let o=Wo(t);if(!o)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${Ct.map(s=>s.id).join(", ")}`);if(o.id==="none"){z(e,"notifications");return}o.envVars.length>0&&oe(e,{category:"Notifications",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"NOTIFICATIONS_PROVIDER",o.id)}import mn from"fs";import ha from"path";async function zo(e,t){let n=ha.join(e,"package.json");if(mn.existsSync(n)){let o=mn.readFileSync(n,"utf8"),s=JSON.parse(o);s.name=t,s.version="0.1.0",mn.writeFileSync(n,JSON.stringify(s,null,2)+`
1741
- `)}}import xt from"fs";import Je from"path";import{fileURLToPath as Ea}from"url";var va=Ea(import.meta.url),Jo=Je.dirname(va);function ba(){let e=[Je.join(Jo,"..","templates","orm","drizzle"),Je.join(Jo,"..","..","templates","orm","drizzle")];for(let t of e)if(xt.existsSync(t))return t;return null}function Qo(e,t){xt.mkdirSync(t,{recursive:!0});for(let n of xt.readdirSync(e,{withFileTypes:!0})){let o=Je.join(e,n.name),s=Je.join(t,n.name);n.isDirectory()?Qo(o,s):xt.copyFileSync(o,s)}}async function Zo(e,t,n){if(t!=="drizzle")return{applied:!1};if(n!=="postgresql")return{applied:!1,reason:`Drizzle template currently targets Postgres only; --db=${n} keeps Prisma as sole ORM`};let o=ba();if(!o)return{applied:!1,reason:"Drizzle template directory not found in package \u2014 bundling error"};let s=Je.join(e,"packages","platform","db-drizzle");return Qo(o,s),{applied:!0}}import ue from"fs";import dt from"path";var _a=["stripe","lemonsqueezy","chinapay","polar"];function es(e){ue.existsSync(e)&&ue.rmSync(e,{recursive:!0,force:!0})}function Pa(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function wa(e,t){let n=dt.join(e,".env.example");ue.existsSync(n)?ue.appendFileSync(n,`
1742
- `+t):ue.writeFileSync(n,t)}function Aa(e){switch(e){case"stripe":return`# Stripe
1739
+ `}async function Ho(e,t,n="global"){let o=Go(t);if(!o||o.id==="none")return;let r=D.join(e,"apps","web");if(!de.existsSync(r))return;let s=o.id;try{switch(s){case"sentry":la(r),un(r,dn.sentry),dt(e,da());return;case"datadog":ua(r),un(r,dn.datadog),dt(e,ma());return;case"bugsnag":ga(r),un(r,dn.bugsnag),dt(e,fa());return;case"aliyun-arms":ya(r),dt(e,Sa());return;case"tingyun":ha(r),dt(e,Ea());return;default:return}}catch(i){throw console.error(`Failed to apply monitoring selection "${t}":`,i),new Error(`Monitoring scaffold for "${t}" failed \u2014 see stderr for details.`)}}var 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 Wo(e){return Ct.find(t=>t.id===e)}var yd=Ct.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Xo(e,t,n="global"){let o=Wo(t);if(!o)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${Ct.map(r=>r.id).join(", ")}`);if(o.id==="none"){z(e,"notifications");return}o.envVars.length>0&&oe(e,{category:"Notifications",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"NOTIFICATIONS_PROVIDER",o.id)}import mn from"fs";import va from"path";async function zo(e,t){let n=va.join(e,"package.json");if(mn.existsSync(n)){let o=mn.readFileSync(n,"utf8"),r=JSON.parse(o);r.name=t,r.version="0.1.0",mn.writeFileSync(n,JSON.stringify(r,null,2)+`
1740
+ `)}}import xt from"fs";import Qe from"path";import{fileURLToPath as ba}from"url";var _a=ba(import.meta.url),Jo=Qe.dirname(_a);function Pa(){let e=[Qe.join(Jo,"..","templates","orm","drizzle"),Qe.join(Jo,"..","..","templates","orm","drizzle")];for(let t of e)if(xt.existsSync(t))return t;return null}function Qo(e,t){xt.mkdirSync(t,{recursive:!0});for(let n of xt.readdirSync(e,{withFileTypes:!0})){let o=Qe.join(e,n.name),r=Qe.join(t,n.name);n.isDirectory()?Qo(o,r):xt.copyFileSync(o,r)}}async function Zo(e,t,n){if(t!=="drizzle")return{applied:!1};if(n!=="postgresql")return{applied:!1,reason:`Drizzle template currently targets Postgres only; --db=${n} keeps Prisma as sole ORM`};let o=Pa();if(!o)return{applied:!1,reason:"Drizzle template directory not found in package \u2014 bundling error"};let r=Qe.join(e,"packages","platform","db-drizzle");return Qo(o,r),{applied:!0}}import ue from"fs";import ut from"path";var wa=["stripe","lemonsqueezy","chinapay","polar"];function er(e){ue.existsSync(e)&&ue.rmSync(e,{recursive:!0,force:!0})}function Aa(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function Ia(e,t){let n=ut.join(e,".env.example");ue.existsSync(n)?ue.appendFileSync(n,`
1741
+ `+t):ue.writeFileSync(n,t)}function Ca(e){switch(e){case"stripe":return`# Stripe
1743
1742
  STRIPE_SECRET_KEY=
1744
1743
  STRIPE_WEBHOOK_SECRET=
1745
1744
  `;case"lemon":return`# Lemon Squeezy
@@ -1754,14 +1753,14 @@ CHINAPAY_WECHAT_ENABLED=true
1754
1753
  CHINAPAY_APP_ID=
1755
1754
  CHINAPAY_APP_SECRET=
1756
1755
  CHINAPAY_ALIPAY_ENABLED=true
1757
- `}}async function ts(e,t){let n=dt.join(e,"packages","commerce","billing");if(!ue.existsSync(n))return;if(t==="none"){es(n);return}let o=dt.join(n,"src"),s=new Set(Pa(t));for(let i of _a)s.has(i)||es(dt.join(o,i));let r=dt.join(o,"checkout","types.ts");if(ue.existsSync(r)){let i=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",a=ue.readFileSync(r,"utf8"),c=a.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${i}";`);c!==a&&ue.writeFileSync(r,c)}wa(e,Aa(t))}import be from"fs";import Qe from"path";var ss=new Set(["siliconflow","volcengine-ark","bailian","moonshot"]),gn=/@sailor:([^\s*]+)/;function Ia(e,t){let{providerIds:n,customEndpoint:o}=t;if(e.startsWith("provider:")){let s=e.slice(9);return{marker:e,keep:n.includes(s)}}if(e==="cn-compatible"){let s=n.some(r=>ss.has(r));return{marker:e,keep:s||!!o}}if(e.startsWith("cn-instance:")){let s=e.slice(12);return{marker:e,keep:n.includes(s)}}return e==="custom-endpoint"?{marker:e,keep:!!o}:e==="registry-entries"?{marker:e,keep:!0}:{marker:e,keep:!0}}function ns(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function os(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function rs(e,t){let n=e.split(`
1758
- `),o=[],s=e.includes("#"),r=0;for(;r<n.length;){let i=n[r],a=i.match(gn);if(!a){o.push(i),r++;continue}let{marker:c,keep:l}=Ia(a[1],t);if(c==="registry-entries"){o.push(s?os(i):ns(i)),r++;continue}if(l){let u=s?os(i):ns(i);u.trim().length>0&&o.push(u);let d=r+1;for(;d<n.length&&n[d].trim()!==""&&!gn.test(n[d]);)o.push(n[d]),d++;d<n.length&&n[d].trim()===""&&(o.push(n[d]),d++),r=d}else{let u=r+1;for(;u<n.length&&n[u].trim()!==""&&!gn.test(n[u]);)u++;u<n.length&&n[u].trim()===""&&u++,r=u}}return Ca(o.join(`
1759
- `),t)}function Ca(e,t){let{providerIds:n,customEndpoint:o}=t,s=new Set;for(let l of n)["openai","anthropic","google","mistral","xai"].includes(l)&&s.add(l),s.add(l.replace(/-/g,"_")),s.add(l);o&&s.add("custom");let r=/createProviderRegistry\(\{([\s\S]*?)\}\)/,i=e.match(r);if(!i)return e;let c=i[1].split(`
1760
- `).filter(l=>{let u=l.trim();if(u===""||u.startsWith("//"))return!0;let d=u.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return d?s.has(d[1]):!0}).join(`
1761
- `);return e.replace(r,`createProviderRegistry({${c}})`)}function xa(e,t){let n=Qe.join(t,"registry.ts.template"),o=be.readFileSync(n,"utf-8");return rs(o,e)}function Ra(e,t){let n=Qe.join(t,".env.example.template"),o=be.readFileSync(n,"utf-8");return rs(o,e)}async function is(e,t,n){let o=xa(t,n),s=Ra(t,n),r=Qe.join(e,"packages/ai/agents/src");await be.promises.mkdir(r,{recursive:!0}),await be.promises.writeFile(Qe.join(r,"registry.ts"),o),await be.promises.appendFile(Qe.join(e,".env.example"),`
1762
- `+s);let i={ai:"latest"},{providerIds:a,customEndpoint:c}=t;(a.includes("openai")||c||a.some(u=>ss.has(u)))&&(i["@ai-sdk/openai"]="latest",i["@ai-sdk/openai-compatible"]="latest"),a.includes("anthropic")&&(i["@ai-sdk/anthropic"]="latest"),a.includes("google")&&(i["@ai-sdk/google"]="latest"),a.includes("mistral")&&(i["@ai-sdk/mistral"]="latest"),a.includes("xai")&&(i["@ai-sdk/openai"]="latest");let l=Qe.join(e,"package.json");if(be.existsSync(l)){let u=JSON.parse(await be.promises.readFile(l,"utf-8"));u.dependencies||(u.dependencies={});for(let[d,_]of Object.entries(i))u.dependencies[d]=_;await be.promises.writeFile(l,JSON.stringify(u,null,2)+`
1763
- `)}}import y from"fs";import g from"path";function as(e,t){if(!y.existsSync(e))return;let n=y.readdirSync(e);for(let o of n){let s=g.join(e,o);y.statSync(s).isDirectory()?as(s,t):t(s)}}async function cs(e,t){let n=g.join(e,"package.json");if(!y.existsSync(n))return;let o=JSON.parse(y.readFileSync(n,"utf8"));if(t.orm!=="prisma"){let s=g.join(e,"packages","db");if(y.existsSync(s)){let r=g.join(s,"prisma");y.existsSync(r)&&y.rmSync(r,{recursive:!0,force:!0});let i=g.join(s,"package.json");if(y.existsSync(i)){let c=JSON.parse(y.readFileSync(i,"utf8"));c.dependencies&&delete c.dependencies["@prisma/client"],c.devDependencies&&delete c.devDependencies.prisma,y.writeFileSync(i,JSON.stringify(c,null,2)+`
1764
- `)}let a=g.join(s,"src","index.ts");y.existsSync(a)&&y.writeFileSync(a,`
1756
+ `}}async function tr(e,t){let n=ut.join(e,"packages","commerce","billing");if(!ue.existsSync(n))return;if(t==="none"){er(n);return}let o=ut.join(n,"src"),r=new Set(Aa(t));for(let i of wa)r.has(i)||er(ut.join(o,i));let s=ut.join(o,"checkout","types.ts");if(ue.existsSync(s)){let i=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",a=ue.readFileSync(s,"utf8"),c=a.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${i}";`);c!==a&&ue.writeFileSync(s,c)}Ia(e,Ca(t))}import _e from"fs";import Ze from"path";var rr=new Set(["siliconflow","volcengine-ark","bailian","moonshot"]),gn=/@sailor:([^\s*]+)/;function xa(e,t){let{providerIds:n,customEndpoint:o}=t;if(e.startsWith("provider:")){let r=e.slice(9);return{marker:e,keep:n.includes(r)}}if(e==="cn-compatible"){let r=n.some(s=>rr.has(s));return{marker:e,keep:r||!!o}}if(e.startsWith("cn-instance:")){let r=e.slice(12);return{marker:e,keep:n.includes(r)}}return e==="custom-endpoint"?{marker:e,keep:!!o}:e==="registry-entries"?{marker:e,keep:!0}:{marker:e,keep:!0}}function nr(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function or(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function sr(e,t){let n=e.split(`
1757
+ `),o=[],r=e.includes("#"),s=0;for(;s<n.length;){let i=n[s],a=i.match(gn);if(!a){o.push(i),s++;continue}let{marker:c,keep:p}=xa(a[1],t);if(c==="registry-entries"){o.push(r?or(i):nr(i)),s++;continue}if(p){let u=r?or(i):nr(i);u.trim().length>0&&o.push(u);let d=s+1;for(;d<n.length&&n[d].trim()!==""&&!gn.test(n[d]);)o.push(n[d]),d++;d<n.length&&n[d].trim()===""&&(o.push(n[d]),d++),s=d}else{let u=s+1;for(;u<n.length&&n[u].trim()!==""&&!gn.test(n[u]);)u++;u<n.length&&n[u].trim()===""&&u++,s=u}}return Ra(o.join(`
1758
+ `),t)}function Ra(e,t){let{providerIds:n,customEndpoint:o}=t,r=new Set;for(let p of n)["openai","anthropic","google","mistral","xai"].includes(p)&&r.add(p),r.add(p.replace(/-/g,"_")),r.add(p);o&&r.add("custom");let s=/createProviderRegistry\(\{([\s\S]*?)\}\)/,i=e.match(s);if(!i)return e;let c=i[1].split(`
1759
+ `).filter(p=>{let u=p.trim();if(u===""||u.startsWith("//"))return!0;let d=u.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return d?r.has(d[1]):!0}).join(`
1760
+ `);return e.replace(s,`createProviderRegistry({${c}})`)}function ka(e,t){let n=Ze.join(t,"registry.ts.template"),o=_e.readFileSync(n,"utf-8");return sr(o,e)}function Ta(e,t){let n=Ze.join(t,".env.example.template"),o=_e.readFileSync(n,"utf-8");return sr(o,e)}async function ir(e,t,n){let o=ka(t,n),r=Ta(t,n),s=Ze.join(e,"packages/ai/agents/src");await _e.promises.mkdir(s,{recursive:!0}),await _e.promises.writeFile(Ze.join(s,"registry.ts"),o),await _e.promises.appendFile(Ze.join(e,".env.example"),`
1761
+ `+r);let i={ai:"latest"},{providerIds:a,customEndpoint:c}=t;(a.includes("openai")||c||a.some(u=>rr.has(u)))&&(i["@ai-sdk/openai"]="latest",i["@ai-sdk/openai-compatible"]="latest"),a.includes("anthropic")&&(i["@ai-sdk/anthropic"]="latest"),a.includes("google")&&(i["@ai-sdk/google"]="latest"),a.includes("mistral")&&(i["@ai-sdk/mistral"]="latest"),a.includes("xai")&&(i["@ai-sdk/openai"]="latest");let p=Ze.join(e,"package.json");if(_e.existsSync(p)){let u=JSON.parse(await _e.promises.readFile(p,"utf-8"));u.dependencies||(u.dependencies={});for(let[d,_]of Object.entries(i))u.dependencies[d]=_;await _e.promises.writeFile(p,JSON.stringify(u,null,2)+`
1762
+ `)}}import y from"fs";import g from"path";function ar(e,t){if(!y.existsSync(e))return;let n=y.readdirSync(e);for(let o of n){let r=g.join(e,o);y.statSync(r).isDirectory()?ar(r,t):t(r)}}async function cr(e,t){let n=g.join(e,"package.json");if(!y.existsSync(n))return;let o=JSON.parse(y.readFileSync(n,"utf8"));if(t.orm!=="prisma"){let r=g.join(e,"packages","db");if(y.existsSync(r)){let s=g.join(r,"prisma");y.existsSync(s)&&y.rmSync(s,{recursive:!0,force:!0});let i=g.join(r,"package.json");if(y.existsSync(i)){let c=JSON.parse(y.readFileSync(i,"utf8"));c.dependencies&&delete c.dependencies["@prisma/client"],c.devDependencies&&delete c.devDependencies.prisma,y.writeFileSync(i,JSON.stringify(c,null,2)+`
1763
+ `)}let a=g.join(r,"src","index.ts");y.existsSync(a)&&y.writeFileSync(a,`
1765
1764
  export const prisma = {} as any;
1766
1765
  export const db = {} as any;
1767
1766
  export type PrismaClient = any;
@@ -1807,7 +1806,7 @@ export type UsageAggregate = any;
1807
1806
  export type UsageLedgerEntry = any;
1808
1807
  export type UsageType = any;
1809
1808
  export type UsageLedgerSource = any;
1810
- `)}o.scripts?.postinstall&&(o.scripts.postinstall=o.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let s=g.join(e,"apps");if(y.existsSync(s)){let r=y.readdirSync(s);for(let i of r){let a=g.join(s,i);if(!y.statSync(a).isDirectory())continue;let c=g.join(a,"src","app");if(!y.existsSync(c))continue;["[lang]","[locale]"].forEach(S=>{let m=g.join(c,S);if(y.existsSync(m)){let P=y.readdirSync(m);for(let G of P)y.renameSync(g.join(m,G),g.join(c,G));y.rmdirSync(m)}}),["src/middleware.ts","middleware.ts"].forEach(S=>{let m=g.join(a,S);y.existsSync(m)&&y.rmSync(m)});let l=g.join(a,"src","lib");y.existsSync(l)||y.mkdirSync(l,{recursive:!0});let u=g.join(l,"mock-i18n.ts");y.writeFileSync(u,`
1809
+ `)}o.scripts?.postinstall&&(o.scripts.postinstall=o.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let r=g.join(e,"apps");if(y.existsSync(r)){let s=y.readdirSync(r);for(let i of s){let a=g.join(r,i);if(!y.statSync(a).isDirectory())continue;let c=g.join(a,"src","app");if(!y.existsSync(c))continue;["[lang]","[locale]"].forEach(S=>{let m=g.join(c,S);if(y.existsSync(m)){let P=y.readdirSync(m);for(let G of P)y.renameSync(g.join(m,G),g.join(c,G));y.rmdirSync(m)}}),["src/middleware.ts","middleware.ts"].forEach(S=>{let m=g.join(a,S);y.existsSync(m)&&y.rmSync(m)});let p=g.join(a,"src","lib");y.existsSync(p)||y.mkdirSync(p,{recursive:!0});let u=g.join(p,"mock-i18n.ts");y.writeFileSync(u,`
1811
1810
  import React from 'react';
1812
1811
  export function useTranslations(namespace?: string): any { return (key: string) => key; }
1813
1812
  export function useLocale() { return 'en'; }
@@ -1825,7 +1824,7 @@ export const useRouter = () => ({ push: (...args: any[]) => {}, replace: (...arg
1825
1824
  export default function createMiddleware(...args: any[]) { return (req: any) => req; }
1826
1825
  export function createNavigation(...args: any[]) { return { Link, redirect, usePathname, useRouter, getPathname: () => '/' }; }
1827
1826
  export function defineRouting<T>(config: T): T { return config; }
1828
- `);let _=g.join(l,"mock-i18n.d.ts");y.writeFileSync(_,`declare module '@/lib/mock-i18n' {
1827
+ `);let _=g.join(p,"mock-i18n.d.ts");y.writeFileSync(_,`declare module '@/lib/mock-i18n' {
1829
1828
  export function useTranslations(namespace?: string): any;
1830
1829
  export function useLocale(): string;
1831
1830
  export const NextIntlClientProvider: React.FC<any>;
@@ -1843,19 +1842,19 @@ export function defineRouting<T>(config: T): T { return config; }
1843
1842
  export function createNavigation(...args: any[]): any;
1844
1843
  export function defineRouting<T>(config: T): T;
1845
1844
  }
1846
- `),y.writeFileSync(g.join(l,"mock-i18n-index.ts"),`
1845
+ `),y.writeFileSync(g.join(p,"mock-i18n-index.ts"),`
1847
1846
  export * from './mock-i18n';
1848
1847
  export { default } from './mock-i18n';
1849
1848
  `);let h=g.join(a,"tsconfig.json");if(y.existsSync(h))try{let S=y.readFileSync(h,"utf8");if(S.includes('"paths": {')){let m=S.replace(/"paths":\s*\{/,`"paths": {
1850
1849
  "next-intl": ["./src/lib/mock-i18n"],
1851
- "next-intl/*": ["./src/lib/mock-i18n"],`);y.writeFileSync(h,m)}}catch{}let f=g.join(a,"src");y.existsSync(f)&&as(f,S=>{if(!S.endsWith(".ts")&&!S.endsWith(".tsx"))return;let m=y.readFileSync(S,"utf8"),P=!1;S.endsWith("src/app/layout.tsx")&&m.includes("../providers")&&(m=m.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),P=!0),m=m.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),m=m.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),m.match(/locale\s*:\s*any/)&&(m=m.replace(/locale\s*:\s*any/g,"locale: string"),P=!0),m.match(/lang\s*:\s*any/)&&(m=m.replace(/lang\s*:\s*any/g,"lang: string"),P=!0),m.match(/requestLocale\s*:\s*any/)&&(m=m.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),P=!0),m.match(/\(locale\s*=\s*(.*)\)/)&&(m=m.replace(/\(locale\s*=\s*(.*)\)/g,"() "),P=!0),m.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(m=m.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 })"),P=!0),(S.endsWith("src/app/layout.tsx")||S.endsWith("src/app/sitemap.ts")||S.endsWith("src/app/robots.ts")||S.endsWith("src/components/ui/locale-switcher.tsx")||S.endsWith("src/app/(marketing)/blog/[slug]/page.tsx"))&&(m=m.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),m=m.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),m=m.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),m=m.replace(/\(l\)\s*=>/g,"(l: any) =>"),P=!0),S.endsWith("src/i18n/request.ts")&&(m=m.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),P=!0),(m.match(/locale\s*:/)||m.match(/lang\s*:/))&&(P=!0),P&&y.writeFileSync(S,m)});let E=g.join(a,"package.json");if(y.existsSync(E)){let S=JSON.parse(y.readFileSync(E,"utf8"));S.dependencies&&delete S.dependencies["next-intl"],y.writeFileSync(E,JSON.stringify(S,null,2)+`
1850
+ "next-intl/*": ["./src/lib/mock-i18n"],`);y.writeFileSync(h,m)}}catch{}let f=g.join(a,"src");y.existsSync(f)&&ar(f,S=>{if(!S.endsWith(".ts")&&!S.endsWith(".tsx"))return;let m=y.readFileSync(S,"utf8"),P=!1;S.endsWith("src/app/layout.tsx")&&m.includes("../providers")&&(m=m.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),P=!0),m=m.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),m=m.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),m.match(/locale\s*:\s*any/)&&(m=m.replace(/locale\s*:\s*any/g,"locale: string"),P=!0),m.match(/lang\s*:\s*any/)&&(m=m.replace(/lang\s*:\s*any/g,"lang: string"),P=!0),m.match(/requestLocale\s*:\s*any/)&&(m=m.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),P=!0),m.match(/\(locale\s*=\s*(.*)\)/)&&(m=m.replace(/\(locale\s*=\s*(.*)\)/g,"() "),P=!0),m.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(m=m.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 })"),P=!0),(S.endsWith("src/app/layout.tsx")||S.endsWith("src/app/sitemap.ts")||S.endsWith("src/app/robots.ts")||S.endsWith("src/components/ui/locale-switcher.tsx")||S.endsWith("src/app/(marketing)/blog/[slug]/page.tsx"))&&(m=m.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),m=m.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),m=m.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),m=m.replace(/\(l\)\s*=>/g,"(l: any) =>"),P=!0),S.endsWith("src/i18n/request.ts")&&(m=m.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),P=!0),(m.match(/locale\s*:/)||m.match(/lang\s*:/))&&(P=!0),P&&y.writeFileSync(S,m)});let E=g.join(a,"package.json");if(y.existsSync(E)){let S=JSON.parse(y.readFileSync(E,"utf8"));S.dependencies&&delete S.dependencies["next-intl"],y.writeFileSync(E,JSON.stringify(S,null,2)+`
1852
1851
  `)}}}}y.writeFileSync(n,JSON.stringify(o,null,2)+`
1853
- `)}function b(e){try{y.rmSync(e,{recursive:!0,force:!0})}catch{}}function ka(e,t){if(!y.existsSync(e))return;let n;try{n=JSON.parse(y.readFileSync(e,"utf8"))}catch{return}let o=!1;if(n.dependencies&&t in n.dependencies){let{[t]:s,...r}=n.dependencies;n={...n,dependencies:r},o=!0}if(n.devDependencies&&t in n.devDependencies){let{[t]:s,...r}=n.devDependencies;n={...n,devDependencies:r},o=!0}o&&y.writeFileSync(e,JSON.stringify(n,null,2)+`
1854
- `)}function ps(e,t){t.cronJobs||(b(g.join(e,"apps/web/src/app/api/cron")),b(g.join(e,"packages/integrations/queue/src/scheduled"))),t.auditLog||(b(g.join(e,"apps/web/src/app/[locale]/(app)/settings/audit-log")),b(g.join(e,"apps/web/src/app/api/audit-logs")),b(g.join(e,"apps/web/src/components/audit"))),t.apiKeys||(b(g.join(e,"apps/web/src/app/[locale]/(app)/settings/api-keys")),b(g.join(e,"apps/web/src/app/api/api-keys")),b(g.join(e,"apps/web/src/components/api-keys"))),t.webhooks||(b(g.join(e,"apps/web/src/app/[locale]/(app)/settings/webhooks")),b(g.join(e,"apps/web/src/app/api/webhooks")),b(g.join(e,"apps/web/src/components/webhooks")),b(g.join(e,"packages/integrations/webhooks"))),t.commandPalette||(b(g.join(e,"apps/web/src/components/command-palette")),b(g.join(e,"apps/web/src/app/[locale]/providers/command-palette-mount.tsx"))),t.cookieConsent||(b(g.join(e,"apps/landing-page/src/components/cookie-consent-banner.tsx")),b(g.join(e,"apps/landing-page/src/components/__tests__/cookie-consent-banner.test.tsx")),b(g.join(e,"apps/landing-page/src/lib/cookie-consent.ts")),b(g.join(e,"apps/landing-page/src/lib/__tests__/cookie-consent.test.ts")),b(g.join(e,"apps/web/src/app/api/cookie-consent"))),t.legalPages||(b(g.join(e,"apps/landing-page/src/app/[lang]/(legal)/legal")),b(g.join(e,"apps/landing-page/src/lib/legal-documents.ts")),b(g.join(e,"apps/landing-page/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(b(g.join(e,"packages/ops/china-compliance")),b(g.join(e,"apps/landing-page/src/components/icp-footer.tsx")),b(g.join(e,"apps/landing-page/src/components/__tests__/icp-footer.test.tsx")),b(g.join(e,"apps/web/src/components/auth/wechat-login-button.tsx")),b(g.join(e,"apps/web/src/components/auth/__tests__/wechat-login-button.test.tsx")),ka(g.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import Ze from"fs";import ls from"path";var ds=/^--\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/m;function Ta(e){let t=ds.exec(e);if(!t)return null;let[,n,o]=t,s=o.split("|").map(r=>r.trim()).filter(Boolean);return{flag:n,values:s}}function Na(e){return e.replace(ds,"").replace(/^\n/,"")}function fn(e,t){let n={kept:[],removed:[],skipped:[]};if(!Ze.existsSync(e))return n;let o=Ze.readdirSync(e,{withFileTypes:!0}).filter(s=>s.isDirectory()).sort((s,r)=>s.name.localeCompare(r.name));for(let s of o){let r=ls.join(e,s.name),i=ls.join(r,"migration.sql");if(!Ze.existsSync(i)){n.skipped.push(s.name);continue}let a=Ze.readFileSync(i,"utf8"),c=Ta(a);if(!c){n.skipped.push(s.name);continue}let l=t[c.flag];if(l!==void 0&&c.values.includes(l)){Ze.writeFileSync(i,Na(a)),n.kept.push(s.name);continue}Ze.rmSync(r,{recursive:!0,force:!0}),n.removed.push(s.name)}return n}import{getSchema as Oa,printSchema as La}from"@mrleebo/prisma-ast";var Ua=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function Ma(e){return e.type==="comment"&&e.text.trim().startsWith("//")}function Da(e){let t=Ua.exec(e.trim());if(!t)return null;let[,n,o]=t,s=o.split("|").map(r=>r.trim()).filter(r=>r.length>0);return{flag:n,values:s}}function Fa(e,t){for(let n=t-1;n>=0;n--){let o=e[n];if(o.type==="comment"){let s=Da(o.text);if(s)return{annIndex:n,parsed:s};continue}break}return null}function ja(e){return e.type==="model"||e.type==="enum"}function yn(e,t){let n=Oa(e),o=new Set;for(let a=0;a<n.list.length;a++){let c=n.list[a];if(!ja(c))continue;let l=Fa(n.list,a);if(!l)continue;let u=t[l.parsed.flag];if(u!==void 0&&l.parsed.values.includes(u))o.add(l.annIndex);else{o.add(a);for(let h=a-1;h>=0;h--){let f=n.list[h];if(Ma(f)){o.add(h);continue}break}let _=n.list[a+1];_&&_.type==="break"&&o.add(a+1)}}let s=n.list.filter((a,c)=>!o.has(c)),r=[];for(let a of s){let c=r[r.length-1];a.type==="break"&&c&&c.type==="break"||r.push(a)}return La({type:"schema",list:r})}import et from"fs";import ms from"path";var Rt=[{id:"qstash",name:"Upstash QStash",region:"both",envVars:["QSTASH_TOKEN","QSTASH_CURRENT_SIGNING_KEY","QSTASH_NEXT_SIGNING_KEY"],docs:"https://upstash.com/docs/qstash",description:"Serverless HTTP-based queue"},{id:"bullmq",name:"BullMQ",region:"both",envVars:["REDIS_URL"],docs:"https://docs.bullmq.io",description:"Redis-backed job queue"},{id:"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 us(e){return Rt.find(t=>t.id===e)}var Bd=Rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function gs(e){return et.existsSync(e)?et.readFileSync(e,"utf-8"):null}function Ba(e,t){let n=ms.join(e,".env.example"),o=gs(n);if(o===null)return;let s=`# Queue: ${t.name}`;if(o.includes(s))return;let r=["","# =============================================",s,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1855
- `);et.appendFileSync(n,r)}function Va(e,t,n){let o=ms.join(e,".env.example"),s=gs(o);if(s===null)return;let r=new RegExp(`^${t}=.*$`,"m");r.test(s)?et.writeFileSync(o,s.replace(r,`${t}="${n}"`)):et.appendFileSync(o,`${t}="${n}"
1856
- `)}async function fs(e,t,n){let o=xe(e,"queue");if(t==="none"){o&&et.rmSync(o,{recursive:!0,force:!0});return}let s=us(t);if(!s)throw new Error(`Unknown queue provider "${t}". Valid ids: ${Rt.map(r=>r.id).join(", ")}`);o&&(Ba(e,s),Va(e,"QUEUE_PROVIDER",t))}import me from"fs";import _e from"path";import{fileURLToPath as Ka}from"url";var $a=Ka(import.meta.url),ys=_e.dirname($a),Ya=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|toml|py)$/,qa=["backends/gateway","infra","e2e","tests"];function Ga(){let e=[_e.join(ys,"..","templates"),_e.join(ys,"..","..","templates")];for(let t of e)if(me.existsSync(t))return t;return e[0]}async function Ss(e,t){let n=Ga(),o=[],s=[],r=[...qa,...t.withWorkflows?["workflows"]:[],...t.withPythonBackend?["backends/python"]:[]];for(let i of r){let a=_e.join(n,i);if(!me.existsSync(a)){s.push(i);continue}let c=_e.join(e,i);hs(a,c),Es(c,{"{PRODUCT_NAME}":t.projectName}),o.push(i)}return{applied:o,skipped:s}}function hs(e,t){me.mkdirSync(t,{recursive:!0});for(let n of me.readdirSync(e,{withFileTypes:!0})){let o=_e.join(e,n.name),s=_e.join(t,n.name);n.isDirectory()?hs(o,s):me.existsSync(s)||me.copyFileSync(o,s)}}function Es(e,t){for(let n of me.readdirSync(e,{withFileTypes:!0})){let o=_e.join(e,n.name);if(n.isDirectory()){Es(o,t);continue}if(!Ya.test(n.name))continue;let s=me.readFileSync(o,"utf-8"),r=!1;for(let[i,a]of Object.entries(t))s.includes(i)&&(s=s.split(i).join(a),r=!0);r&&me.writeFileSync(o,s)}}import tt from"fs";import bs from"path";var kt=[{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 vs(e){return kt.find(t=>t.id===e)}var Jd=kt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function _s(e){return tt.existsSync(e)?tt.readFileSync(e,"utf-8"):null}function Ha(e,t){let n=bs.join(e,".env.example"),o=_s(n);if(o===null)return;let s=`# Search: ${t.name}`;if(o.includes(s))return;let r=["","# =============================================",s,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1857
- `);tt.appendFileSync(n,r)}function Wa(e,t,n){let o=bs.join(e,".env.example"),s=_s(o);if(s===null)return;let r=new RegExp(`^${t}=.*$`,"m");r.test(s)?tt.writeFileSync(o,s.replace(r,`${t}="${n}"`)):tt.appendFileSync(o,`${t}="${n}"
1858
- `)}async function Ps(e,t,n){let o=xe(e,"search");if(t==="none"){o&&tt.rmSync(o,{recursive:!0,force:!0});return}let s=vs(t);if(!s)throw new Error(`Unknown search provider "${t}". Valid ids: ${kt.map(r=>r.id).join(", ")}`);o&&(Ha(e,s),Wa(e,"SEARCH_PROVIDER",t))}import Pe from"fs";import Me from"path";function Xa(e){let t=[Me.join(e,"packages","db"),Me.join(e,"apps","web")];for(let n of t){let o=Me.join(n,"prisma","schema.prisma");if(Pe.existsSync(o))return{packageDir:n,seedPath:Me.join(n,"prisma","seed.ts"),packageJsonPath:Me.join(n,"package.json")}}return null}function za(e){try{let t=Pe.readFileSync(e,"utf8"),n=new Set,o=/^\s*model\s+(\w+)\s*\{/gm,s=o.exec(t);for(;s;)n.add(s[1]),s=o.exec(t);return n}catch{return new Set}}function Ja(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
1852
+ `)}function b(e){try{y.rmSync(e,{recursive:!0,force:!0})}catch{}}function Na(e,t){if(!y.existsSync(e))return;let n;try{n=JSON.parse(y.readFileSync(e,"utf8"))}catch{return}let o=!1;if(n.dependencies&&t in n.dependencies){let{[t]:r,...s}=n.dependencies;n={...n,dependencies:s},o=!0}if(n.devDependencies&&t in n.devDependencies){let{[t]:r,...s}=n.devDependencies;n={...n,devDependencies:s},o=!0}o&&y.writeFileSync(e,JSON.stringify(n,null,2)+`
1853
+ `)}function pr(e,t){t.cronJobs||(b(g.join(e,"apps/web/src/app/api/cron")),b(g.join(e,"packages/integrations/queue/src/scheduled"))),t.auditLog||(b(g.join(e,"apps/web/src/app/[locale]/(app)/settings/audit-log")),b(g.join(e,"apps/web/src/app/api/audit-logs")),b(g.join(e,"apps/web/src/components/audit"))),t.apiKeys||(b(g.join(e,"apps/web/src/app/[locale]/(app)/settings/api-keys")),b(g.join(e,"apps/web/src/app/api/api-keys")),b(g.join(e,"apps/web/src/components/api-keys"))),t.webhooks||(b(g.join(e,"apps/web/src/app/[locale]/(app)/settings/webhooks")),b(g.join(e,"apps/web/src/app/api/webhooks")),b(g.join(e,"apps/web/src/components/webhooks")),b(g.join(e,"packages/integrations/webhooks"))),t.commandPalette||(b(g.join(e,"apps/web/src/components/command-palette")),b(g.join(e,"apps/web/src/app/[locale]/providers/command-palette-mount.tsx"))),t.cookieConsent||(b(g.join(e,"apps/landing-page/src/components/cookie-consent-banner.tsx")),b(g.join(e,"apps/landing-page/src/components/__tests__/cookie-consent-banner.test.tsx")),b(g.join(e,"apps/landing-page/src/lib/cookie-consent.ts")),b(g.join(e,"apps/landing-page/src/lib/__tests__/cookie-consent.test.ts")),b(g.join(e,"apps/web/src/app/api/cookie-consent"))),t.legalPages||(b(g.join(e,"apps/landing-page/src/app/[lang]/(legal)/legal")),b(g.join(e,"apps/landing-page/src/lib/legal-documents.ts")),b(g.join(e,"apps/landing-page/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(b(g.join(e,"packages/ops/china-compliance")),b(g.join(e,"apps/landing-page/src/components/icp-footer.tsx")),b(g.join(e,"apps/landing-page/src/components/__tests__/icp-footer.test.tsx")),b(g.join(e,"apps/web/src/components/auth/wechat-login-button.tsx")),b(g.join(e,"apps/web/src/components/auth/__tests__/wechat-login-button.test.tsx")),Na(g.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import et from"fs";import lr from"path";var dr=/^--\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/m;function Oa(e){let t=dr.exec(e);if(!t)return null;let[,n,o]=t,r=o.split("|").map(s=>s.trim()).filter(Boolean);return{flag:n,values:r}}function La(e){return e.replace(dr,"").replace(/^\n/,"")}function fn(e,t){let n={kept:[],removed:[],skipped:[]};if(!et.existsSync(e))return n;let o=et.readdirSync(e,{withFileTypes:!0}).filter(r=>r.isDirectory()).sort((r,s)=>r.name.localeCompare(s.name));for(let r of o){let s=lr.join(e,r.name),i=lr.join(s,"migration.sql");if(!et.existsSync(i)){n.skipped.push(r.name);continue}let a=et.readFileSync(i,"utf8"),c=Oa(a);if(!c){n.skipped.push(r.name);continue}let p=t[c.flag];if(p!==void 0&&c.values.includes(p)){et.writeFileSync(i,La(a)),n.kept.push(r.name);continue}et.rmSync(s,{recursive:!0,force:!0}),n.removed.push(r.name)}return n}import{getSchema as Ua,printSchema as Ma}from"@mrleebo/prisma-ast";var Da=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function Fa(e){return e.type==="comment"&&e.text.trim().startsWith("//")}function ja(e){let t=Da.exec(e.trim());if(!t)return null;let[,n,o]=t,r=o.split("|").map(s=>s.trim()).filter(s=>s.length>0);return{flag:n,values:r}}function Ba(e,t){for(let n=t-1;n>=0;n--){let o=e[n];if(o.type==="comment"){let r=ja(o.text);if(r)return{annIndex:n,parsed:r};continue}break}return null}function Va(e){return e.type==="model"||e.type==="enum"}function yn(e,t){let n=Ua(e),o=new Set;for(let a=0;a<n.list.length;a++){let c=n.list[a];if(!Va(c))continue;let p=Ba(n.list,a);if(!p)continue;let u=t[p.parsed.flag];if(u!==void 0&&p.parsed.values.includes(u))o.add(p.annIndex);else{o.add(a);for(let h=a-1;h>=0;h--){let f=n.list[h];if(Fa(f)){o.add(h);continue}break}let _=n.list[a+1];_&&_.type==="break"&&o.add(a+1)}}let r=n.list.filter((a,c)=>!o.has(c)),s=[];for(let a of r){let c=s[s.length-1];a.type==="break"&&c&&c.type==="break"||s.push(a)}return Ma({type:"schema",list:s})}import tt from"fs";import mr from"path";var Rt=[{id:"qstash",name:"Upstash QStash",region:"both",envVars:["QSTASH_TOKEN","QSTASH_CURRENT_SIGNING_KEY","QSTASH_NEXT_SIGNING_KEY"],docs:"https://upstash.com/docs/qstash",description:"Serverless HTTP-based queue"},{id:"bullmq",name:"BullMQ",region:"both",envVars:["REDIS_URL"],docs:"https://docs.bullmq.io",description:"Redis-backed job queue"},{id:"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 ur(e){return Rt.find(t=>t.id===e)}var Kd=Rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function gr(e){return tt.existsSync(e)?tt.readFileSync(e,"utf-8"):null}function Ka(e,t){let n=mr.join(e,".env.example"),o=gr(n);if(o===null)return;let r=`# Queue: ${t.name}`;if(o.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1854
+ `);tt.appendFileSync(n,s)}function $a(e,t,n){let o=mr.join(e,".env.example"),r=gr(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?tt.writeFileSync(o,r.replace(s,`${t}="${n}"`)):tt.appendFileSync(o,`${t}="${n}"
1855
+ `)}async function fr(e,t,n){let o=Re(e,"queue");if(t==="none"){o&&tt.rmSync(o,{recursive:!0,force:!0});return}let r=ur(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${Rt.map(s=>s.id).join(", ")}`);o&&(Ka(e,r),$a(e,"QUEUE_PROVIDER",t))}import me from"fs";import Pe from"path";import{fileURLToPath as Ya}from"url";var qa=Ya(import.meta.url),yr=Pe.dirname(qa),Ga=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|toml|py)$/,Ha=["backends/gateway","infra","e2e","tests"];function Wa(){let e=[Pe.join(yr,"..","templates"),Pe.join(yr,"..","..","templates")];for(let t of e)if(me.existsSync(t))return t;return e[0]}async function Sr(e,t){let n=Wa(),o=[],r=[],s=[...Ha,...t.withWorkflows?["workflows"]:[],...t.withPythonBackend?["backends/python"]:[]];for(let i of s){let a=Pe.join(n,i);if(!me.existsSync(a)){r.push(i);continue}let c=Pe.join(e,i);hr(a,c),Er(c,{"{PRODUCT_NAME}":t.projectName}),o.push(i)}return{applied:o,skipped:r}}function hr(e,t){me.mkdirSync(t,{recursive:!0});for(let n of me.readdirSync(e,{withFileTypes:!0})){let o=Pe.join(e,n.name),r=Pe.join(t,n.name);n.isDirectory()?hr(o,r):me.existsSync(r)||me.copyFileSync(o,r)}}function Er(e,t){for(let n of me.readdirSync(e,{withFileTypes:!0})){let o=Pe.join(e,n.name);if(n.isDirectory()){Er(o,t);continue}if(!Ga.test(n.name))continue;let r=me.readFileSync(o,"utf-8"),s=!1;for(let[i,a]of Object.entries(t))r.includes(i)&&(r=r.split(i).join(a),s=!0);s&&me.writeFileSync(o,r)}}import nt from"fs";import br from"path";var kt=[{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 vr(e){return kt.find(t=>t.id===e)}var Zd=kt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function _r(e){return nt.existsSync(e)?nt.readFileSync(e,"utf-8"):null}function Xa(e,t){let n=br.join(e,".env.example"),o=_r(n);if(o===null)return;let r=`# Search: ${t.name}`;if(o.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1856
+ `);nt.appendFileSync(n,s)}function za(e,t,n){let o=br.join(e,".env.example"),r=_r(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?nt.writeFileSync(o,r.replace(s,`${t}="${n}"`)):nt.appendFileSync(o,`${t}="${n}"
1857
+ `)}async function Pr(e,t,n){let o=Re(e,"search");if(t==="none"){o&&nt.rmSync(o,{recursive:!0,force:!0});return}let r=vr(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${kt.map(s=>s.id).join(", ")}`);o&&(Xa(e,r),za(e,"SEARCH_PROVIDER",t))}import we from"fs";import De from"path";function Ja(e){let t=[De.join(e,"packages","db"),De.join(e,"apps","web")];for(let n of t){let o=De.join(n,"prisma","schema.prisma");if(we.existsSync(o))return{packageDir:n,seedPath:De.join(n,"prisma","seed.ts"),packageJsonPath:De.join(n,"package.json")}}return null}function Qa(e){try{let t=we.readFileSync(e,"utf8"),n=new Set,o=/^\s*model\s+(\w+)\s*\{/gm,r=o.exec(t);for(;r;)n.add(r[1]),r=o.exec(t);return n}catch{return new Set}}function Za(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
1859
1858
  const admin = await prisma.user.create({
1860
1859
  data: {
1861
1860
  clerkId: "user_mock_admin",
@@ -1886,7 +1885,7 @@ export { default } from './mock-i18n';
1886
1885
  console.log("\\u2713 Created admin user:", admin.email);
1887
1886
  } catch (err) {
1888
1887
  console.warn("\\u26A0 Admin user creation skipped:", (err as Error).message);
1889
- }`}function Qa(e,t){let n=t.has("Tenant"),o=t.has("User"),s=t.has("Project"),r=Ja(e,o),i=n?` let tenants: Array<{ id: string; name: string }> = [];
1888
+ }`}function ec(e,t){let n=t.has("Tenant"),o=t.has("User"),r=t.has("Project"),s=Za(e,o),i=n?` let tenants: Array<{ id: string; name: string }> = [];
1890
1889
  try {
1891
1890
  tenants = await Promise.all([
1892
1891
  prisma.tenant.create({
@@ -1903,7 +1902,7 @@ export { default } from './mock-i18n';
1903
1902
  } catch (err) {
1904
1903
  console.warn("\\u26A0 Tenant creation skipped:", (err as Error).message);
1905
1904
  }`:` const tenants: Array<{ id: string; name: string }> = [];
1906
- console.log("\\u2139 No Tenant model in schema \u2014 skipping tenant seed.");`,a=s&&n?` for (const tenant of tenants) {
1905
+ console.log("\\u2139 No Tenant model in schema \u2014 skipping tenant seed.");`,a=r&&n?` for (const tenant of tenants) {
1907
1906
  try {
1908
1907
  await prisma.project.createMany({
1909
1908
  data: [
@@ -1939,7 +1938,7 @@ async function main(): Promise<void> {
1939
1938
  ${i}
1940
1939
 
1941
1940
  // --- Admin user ------------------------------------------------------
1942
- ${r}
1941
+ ${s}
1943
1942
 
1944
1943
  // --- Sample projects per tenant --------------------------------------
1945
1944
  ${a}
@@ -1955,12 +1954,12 @@ main()
1955
1954
  .finally(async () => {
1956
1955
  await prisma.$disconnect();
1957
1956
  });
1958
- `}function Za(e){if(Pe.existsSync(e))try{let t=Pe.readFileSync(e,"utf8"),n=JSON.parse(t),o=n.scripts??{},s=!1;o["db:seed"]||(o["db:seed"]="prisma db seed",s=!0);let r=n.prisma??{};if(r.seed||(r.seed="tsx prisma/seed.ts",s=!0),!s)return;let i={...n,scripts:o,prisma:r};Pe.writeFileSync(e,JSON.stringify(i,null,2)+`
1959
- `)}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`[create-sailor] Failed to patch seed scripts in ${e}: ${n}`)}}async function ws(e,t){let n=Xa(e);if(n)try{let o=Me.join(n.packageDir,"prisma","schema.prisma"),s=za(o),r=Qa(t,s),i=Me.dirname(n.seedPath);Pe.existsSync(i)||Pe.mkdirSync(i,{recursive:!0}),Pe.writeFileSync(n.seedPath,r),Za(n.packageJsonPath)}catch(o){let s=o instanceof Error?o.message:String(o);throw console.error(`[create-sailor] Failed to generate seed data: ${s}`),new Error(`Unable to write prisma/seed.ts: ${s}`)}}import we from"fs";import De from"path";var Tt=[{id:"twilio",name:"Twilio",region:"global",envVars:["TWILIO_ACCOUNT_SID","TWILIO_AUTH_TOKEN","TWILIO_FROM_NUMBER"],docs:"https://www.twilio.com/docs/sms",pkgs:["twilio"]},{id:"messagebird",name:"MessageBird (Bird)",region:"global",envVars:["MESSAGEBIRD_ACCESS_KEY","MESSAGEBIRD_ORIGINATOR"],docs:"https://developers.messagebird.com/api/sms-messaging/",pkgs:["messagebird"]},{id:"plivo",name:"Plivo",region:"global",envVars:["PLIVO_AUTH_ID","PLIVO_AUTH_TOKEN","PLIVO_FROM_NUMBER"],docs:"https://www.plivo.com/docs/sms/",pkgs:["plivo"]},{id:"aliyun-sms",name:"\u963F\u91CC\u4E91\u77ED\u4FE1 Aliyun SMS",region:"cn",envVars:["ALIYUN_SMS_ACCESS_KEY","ALIYUN_SMS_ACCESS_SECRET","ALIYUN_SMS_SIGN_NAME","ALIYUN_SMS_TEMPLATE_CODE","ALIYUN_SMS_ENDPOINT"],docs:"https://help.aliyun.com/product/44282.html",pkgs:["@alicloud/dysmsapi20170525","@alicloud/openapi-client"]},{id:"tencent-sms",name:"\u817E\u8BAF\u4E91\u77ED\u4FE1 Tencent SMS",region:"cn",envVars:["TENCENT_SMS_SECRET_ID","TENCENT_SMS_SECRET_KEY","TENCENT_SMS_SDK_APP_ID","TENCENT_SMS_SIGN_NAME","TENCENT_SMS_TEMPLATE_ID","TENCENT_SMS_REGION"],docs:"https://cloud.tencent.com/document/product/382",pkgs:["tencentcloud-sdk-nodejs-sms"]},{id:"yunpian",name:"\u4E91\u7247 Yunpian",region:"cn",envVars:["YUNPIAN_API_KEY","YUNPIAN_SIGN"],docs:"https://www.yunpian.com/official/document/sms/zh_CN/introduction_product_intro",pkgs:["yunpian-nodejs-sdk"]},{id:"none",name:"None",region:"both",envVars:[],docs:""}],au=Tt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function As(e){return Tt.find(t=>t.id===e)}var ec="@nebutra/sms",tc={twilio:"^5.3.6",messagebird:"^4.0.1",plivo:"^4.73.0","@alicloud/dysmsapi20170525":"^2.0.24","@alicloud/openapi-client":"^0.4.12","tencentcloud-sdk-nodejs-sms":"^4.0.970","yunpian-nodejs-sdk":"^0.0.2"};function Sn(e,t){we.mkdirSync(De.dirname(e),{recursive:!0}),we.writeFileSync(e,t)}function nc(e,t){let n=De.join(e,".env.example");we.existsSync(n)?we.appendFileSync(n,`
1960
- `+t):we.writeFileSync(n,t)}function oc(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
1957
+ `}function tc(e){if(we.existsSync(e))try{let t=we.readFileSync(e,"utf8"),n=JSON.parse(t),o=n.scripts??{},r=!1;o["db:seed"]||(o["db:seed"]="prisma db seed",r=!0);let s=n.prisma??{};if(s.seed||(s.seed="tsx prisma/seed.ts",r=!0),!r)return;let i={...n,scripts:o,prisma:s};we.writeFileSync(e,JSON.stringify(i,null,2)+`
1958
+ `)}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`[create-sailor] Failed to patch seed scripts in ${e}: ${n}`)}}async function wr(e,t){let n=Ja(e);if(n)try{let o=De.join(n.packageDir,"prisma","schema.prisma"),r=Qa(o),s=ec(t,r),i=De.dirname(n.seedPath);we.existsSync(i)||we.mkdirSync(i,{recursive:!0}),we.writeFileSync(n.seedPath,s),tc(n.packageJsonPath)}catch(o){let r=o instanceof Error?o.message:String(o);throw console.error(`[create-sailor] Failed to generate seed data: ${r}`),new Error(`Unable to write prisma/seed.ts: ${r}`)}}import Ae from"fs";import Fe from"path";var Tt=[{id:"twilio",name:"Twilio",region:"global",envVars:["TWILIO_ACCOUNT_SID","TWILIO_AUTH_TOKEN","TWILIO_FROM_NUMBER"],docs:"https://www.twilio.com/docs/sms",pkgs:["twilio"]},{id:"messagebird",name:"MessageBird (Bird)",region:"global",envVars:["MESSAGEBIRD_ACCESS_KEY","MESSAGEBIRD_ORIGINATOR"],docs:"https://developers.messagebird.com/api/sms-messaging/",pkgs:["messagebird"]},{id:"plivo",name:"Plivo",region:"global",envVars:["PLIVO_AUTH_ID","PLIVO_AUTH_TOKEN","PLIVO_FROM_NUMBER"],docs:"https://www.plivo.com/docs/sms/",pkgs:["plivo"]},{id:"aliyun-sms",name:"\u963F\u91CC\u4E91\u77ED\u4FE1 Aliyun SMS",region:"cn",envVars:["ALIYUN_SMS_ACCESS_KEY","ALIYUN_SMS_ACCESS_SECRET","ALIYUN_SMS_SIGN_NAME","ALIYUN_SMS_TEMPLATE_CODE","ALIYUN_SMS_ENDPOINT"],docs:"https://help.aliyun.com/product/44282.html",pkgs:["@alicloud/dysmsapi20170525","@alicloud/openapi-client"]},{id:"tencent-sms",name:"\u817E\u8BAF\u4E91\u77ED\u4FE1 Tencent SMS",region:"cn",envVars:["TENCENT_SMS_SECRET_ID","TENCENT_SMS_SECRET_KEY","TENCENT_SMS_SDK_APP_ID","TENCENT_SMS_SIGN_NAME","TENCENT_SMS_TEMPLATE_ID","TENCENT_SMS_REGION"],docs:"https://cloud.tencent.com/document/product/382",pkgs:["tencentcloud-sdk-nodejs-sms"]},{id:"yunpian",name:"\u4E91\u7247 Yunpian",region:"cn",envVars:["YUNPIAN_API_KEY","YUNPIAN_SIGN"],docs:"https://www.yunpian.com/official/document/sms/zh_CN/introduction_product_intro",pkgs:["yunpian-nodejs-sdk"]},{id:"none",name:"None",region:"both",envVars:[],docs:""}],pu=Tt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ar(e){return Tt.find(t=>t.id===e)}var nc="@nebutra/sms",oc={twilio:"^5.3.6",messagebird:"^4.0.1",plivo:"^4.73.0","@alicloud/dysmsapi20170525":"^2.0.24","@alicloud/openapi-client":"^0.4.12","tencentcloud-sdk-nodejs-sms":"^4.0.970","yunpian-nodejs-sdk":"^0.0.2"};function Sn(e,t){Ae.mkdirSync(Fe.dirname(e),{recursive:!0}),Ae.writeFileSync(e,t)}function rc(e,t){let n=Fe.join(e,".env.example");Ae.existsSync(n)?Ae.appendFileSync(n,`
1959
+ `+t):Ae.writeFileSync(n,t)}function sc(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
1961
1960
  `);return`${t}
1962
1961
  ${n}
1963
- `}var sc=`/**
1962
+ `}var ic=`/**
1964
1963
  * Inputs for the \`sendSms\` wrapper. Keep this surface portable across
1965
1964
  * providers \u2014 provider-specific options belong in the wrapper itself.
1966
1965
  */
@@ -1980,7 +1979,7 @@ export interface SendSmsResult {
1980
1979
  provider: string;
1981
1980
  raw?: unknown;
1982
1981
  }
1983
- `;function rc(){return`import twilio from "twilio";
1982
+ `;function ac(){return`import twilio from "twilio";
1984
1983
  import type { SendSmsInput, SendSmsResult } from "./types";
1985
1984
 
1986
1985
  let client: ReturnType<typeof twilio> | null = null;
@@ -2015,7 +2014,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2015
2014
  }
2016
2015
 
2017
2016
  export type { SendSmsInput, SendSmsResult } from "./types";
2018
- `}function ic(){return`import messagebird from "messagebird";
2017
+ `}function cc(){return`import messagebird from "messagebird";
2019
2018
  import type { SendSmsInput, SendSmsResult } from "./types";
2020
2019
 
2021
2020
  let client: ReturnType<typeof messagebird> | null = null;
@@ -2053,7 +2052,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2053
2052
  }
2054
2053
 
2055
2054
  export type { SendSmsInput, SendSmsResult } from "./types";
2056
- `}function ac(){return`import plivo from "plivo";
2055
+ `}function pc(){return`import plivo from "plivo";
2057
2056
  import type { SendSmsInput, SendSmsResult } from "./types";
2058
2057
 
2059
2058
  let client: InstanceType<typeof plivo.Client> | null = null;
@@ -2092,7 +2091,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2092
2091
  }
2093
2092
 
2094
2093
  export type { SendSmsInput, SendSmsResult } from "./types";
2095
- `}function cc(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2094
+ `}function lc(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2096
2095
  import * as $OpenApi from "@alicloud/openapi-client";
2097
2096
  import type { SendSmsInput, SendSmsResult } from "./types";
2098
2097
 
@@ -2141,7 +2140,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2141
2140
  }
2142
2141
 
2143
2142
  export type { SendSmsInput, SendSmsResult } from "./types";
2144
- `}function pc(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2143
+ `}function dc(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2145
2144
  import type { SendSmsInput, SendSmsResult } from "./types";
2146
2145
 
2147
2146
  const SmsClient = tencentcloud.sms.v20210111.Client;
@@ -2206,7 +2205,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2206
2205
  }
2207
2206
 
2208
2207
  export type { SendSmsInput, SendSmsResult } from "./types";
2209
- `}function lc(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2208
+ `}function uc(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2210
2209
  import Yunpian from "yunpian-nodejs-sdk";
2211
2210
  import type { SendSmsInput, SendSmsResult } from "./types";
2212
2211
 
@@ -2258,13 +2257,13 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2258
2257
  }
2259
2258
 
2260
2259
  export type { SendSmsInput, SendSmsResult } from "./types";
2261
- `}function dc(e){switch(e){case"twilio":return rc();case"messagebird":return ic();case"plivo":return ac();case"aliyun-sms":return cc();case"tencent-sms":return pc();case"yunpian":return lc();case"none":return`export {};
2262
- `}}function uc(e){let t={};for(let o of e.pkgs??[]){let s=tc[o];s&&(t[o]=s)}let n={name:ec,version:"0.1.0",private:!0,description:`Transactional SMS via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
2263
- `}async function Is(e,t,n="global"){if(t==="none")return;let o=As(t);if(!o)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${Tt.map(i=>i.id).join(", ")}`);let s=De.join(e,"packages","sms");if(!we.existsSync(s))return;let r=De.join(s,"src");we.existsSync(r)&&we.rmSync(r,{recursive:!0,force:!0});try{Sn(De.join(s,"package.json"),uc(o)),Sn(De.join(r,"types.ts"),sc),Sn(De.join(r,"index.ts"),dc(o.id)),nc(e,oc(o))}catch(i){throw console.error(`Failed to apply SMS selection "${t}":`,i),new Error(`SMS scaffold for "${t}" failed \u2014 see stderr for details.`)}}import je from"fs";import Fe from"path";var Be="@nebutra/storage";function hn(e,t){je.mkdirSync(Fe.dirname(e),{recursive:!0}),je.writeFileSync(e,t)}function mc(e,t){let n=Fe.join(e,".env.example");je.existsSync(n)?je.appendFileSync(n,`
2264
- `+t):je.writeFileSync(n,t)}function gc(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
2260
+ `}function mc(e){switch(e){case"twilio":return ac();case"messagebird":return cc();case"plivo":return pc();case"aliyun-sms":return lc();case"tencent-sms":return dc();case"yunpian":return uc();case"none":return`export {};
2261
+ `}}function gc(e){let t={};for(let o of e.pkgs??[]){let r=oc[o];r&&(t[o]=r)}let n={name:nc,version:"0.1.0",private:!0,description:`Transactional SMS via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
2262
+ `}async function Ir(e,t,n="global"){if(t==="none")return;let o=Ar(t);if(!o)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${Tt.map(i=>i.id).join(", ")}`);let r=Fe.join(e,"packages","sms");if(!Ae.existsSync(r))return;let s=Fe.join(r,"src");Ae.existsSync(s)&&Ae.rmSync(s,{recursive:!0,force:!0});try{Sn(Fe.join(r,"package.json"),gc(o)),Sn(Fe.join(s,"types.ts"),ic),Sn(Fe.join(s,"index.ts"),mc(o.id)),rc(e,sc(o))}catch(i){throw console.error(`Failed to apply SMS selection "${t}":`,i),new Error(`SMS scaffold for "${t}" failed \u2014 see stderr for details.`)}}import Be from"fs";import je from"path";var Ve="@nebutra/storage";function hn(e,t){Be.mkdirSync(je.dirname(e),{recursive:!0}),Be.writeFileSync(e,t)}function fc(e,t){let n=je.join(e,".env.example");Be.existsSync(n)?Be.appendFileSync(n,`
2263
+ `+t):Be.writeFileSync(n,t)}function yc(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
2265
2264
  `);return`${t}
2266
2265
  ${n}
2267
- `}var fc=`/**
2266
+ `}var Sc=`/**
2268
2267
  * Inputs for the \`uploadFile\` wrapper. Keep this surface portable across
2269
2268
  * providers \u2014 provider-specific options belong in the wrapper itself.
2270
2269
  */
@@ -2290,8 +2289,8 @@ export interface SignedUrlOptions {
2290
2289
  operation?: "get" | "put";
2291
2290
  contentType?: string;
2292
2291
  }
2293
- `;function yc(){return`/**
2294
- * @${Be.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
2292
+ `;function hc(){return`/**
2293
+ * @${Ve.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
2295
2294
  *
2296
2295
  * Docs: https://developers.cloudflare.com/r2/api/s3/api/
2297
2296
  */
@@ -2354,8 +2353,8 @@ export async function getSignedUrl(
2354
2353
  }
2355
2354
 
2356
2355
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2357
- `}function Sc(){return`/**
2358
- * @${Be.slice(1)} \u2014 AWS S3 wrapper.
2356
+ `}function Ec(){return`/**
2357
+ * @${Ve.slice(1)} \u2014 AWS S3 wrapper.
2359
2358
  *
2360
2359
  * Docs: https://docs.aws.amazon.com/s3/
2361
2360
  */
@@ -2419,8 +2418,8 @@ export async function getSignedUrl(
2419
2418
  }
2420
2419
 
2421
2420
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2422
- `}function hc(){return`/**
2423
- * @${Be.slice(1)} \u2014 Supabase Storage wrapper.
2421
+ `}function vc(){return`/**
2422
+ * @${Ve.slice(1)} \u2014 Supabase Storage wrapper.
2424
2423
  *
2425
2424
  * Docs: https://supabase.com/docs/guides/storage
2426
2425
  */
@@ -2482,8 +2481,8 @@ export async function getSignedUrl(
2482
2481
  }
2483
2482
 
2484
2483
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2485
- `}function Ec(){return`/**
2486
- * @${Be.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2484
+ `}function bc(){return`/**
2485
+ * @${Ve.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2487
2486
  *
2488
2487
  * Docs: https://help.aliyun.com/product/31815.html
2489
2488
  */
@@ -2529,8 +2528,8 @@ export async function getSignedUrl(
2529
2528
  }
2530
2529
 
2531
2530
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2532
- `}function vc(){return`/**
2533
- * @${Be.slice(1)} \u2014 \u817E\u8BAF\u4E91 COS wrapper via cos-nodejs-sdk-v5.
2531
+ `}function _c(){return`/**
2532
+ * @${Ve.slice(1)} \u2014 \u817E\u8BAF\u4E91 COS wrapper via cos-nodejs-sdk-v5.
2534
2533
  *
2535
2534
  * Docs: https://cloud.tencent.com/document/product/436
2536
2535
  */
@@ -2584,8 +2583,8 @@ export async function getSignedUrl(
2584
2583
  }
2585
2584
 
2586
2585
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2587
- `}function bc(){return`/**
2588
- * @${Be.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2586
+ `}function Pc(){return`/**
2587
+ * @${Ve.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2589
2588
  *
2590
2589
  * Docs: https://developer.qiniu.com/kodo
2591
2590
  */
@@ -2652,9 +2651,9 @@ export async function getSignedUrl(
2652
2651
  }
2653
2652
 
2654
2653
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2655
- `}function _c(e){switch(e){case"r2":return yc();case"s3":return Sc();case"supabase-storage":return hc();case"aliyun-oss":return Ec();case"tencent-cos":return vc();case"qiniu":return bc();case"none":return`export {};
2656
- `}}function Pc(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),(e.id==="r2"||e.id==="s3")&&(t["@aws-sdk/s3-request-presigner"]="^3.658.0");let n={name:Be,version:"0.1.0",private:!0,description:`Object storage via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
2657
- `}async function Cs(e,t,n){if(t==="none")return;let o=Rn(t);if(!o)throw new Error(`Unknown storage provider "${t}". Valid ids: ${rt.map(i=>i.id).join(", ")}`);let s=Fe.join(e,"packages","storage"),r=Fe.join(s,"src");je.existsSync(r)&&je.rmSync(r,{recursive:!0,force:!0}),hn(Fe.join(s,"package.json"),Pc(o)),hn(Fe.join(r,"types.ts"),fc),hn(Fe.join(r,"index.ts"),_c(o.id)),mc(e,gc(o))}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 xs(e){return Nt.find(t=>t.id===e)}var Su=Nt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Rs(e,t,n="global"){let o=xs(t);if(!o)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Nt.map(s=>s.id).join(", ")}`);if(o.id==="none"){z(e,"webhooks");return}o.envVars.length>0&&oe(e,{category:"Webhooks",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"WEBHOOKS_PROVIDER",o.id)}import Ve from"fs";import ut from"path";function wc(e){return`import { brand } from "@nebutra/brand/metadata";
2654
+ `}function wc(e){switch(e){case"r2":return hc();case"s3":return Ec();case"supabase-storage":return vc();case"aliyun-oss":return bc();case"tencent-cos":return _c();case"qiniu":return Pc();case"none":return`export {};
2655
+ `}}function Ac(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),(e.id==="r2"||e.id==="s3")&&(t["@aws-sdk/s3-request-presigner"]="^3.658.0");let n={name:Ve,version:"0.1.0",private:!0,description:`Object storage via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
2656
+ `}async function Cr(e,t,n){if(t==="none")return;let o=Rn(t);if(!o)throw new Error(`Unknown storage provider "${t}". Valid ids: ${it.map(i=>i.id).join(", ")}`);let r=je.join(e,"packages","storage"),s=je.join(r,"src");Be.existsSync(s)&&Be.rmSync(s,{recursive:!0,force:!0}),hn(je.join(r,"package.json"),Ac(o)),hn(je.join(s,"types.ts"),Sc),hn(je.join(s,"index.ts"),wc(o.id)),fc(e,yc(o))}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 xr(e){return Nt.find(t=>t.id===e)}var Eu=Nt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Rr(e,t,n="global"){let o=xr(t);if(!o)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Nt.map(r=>r.id).join(", ")}`);if(o.id==="none"){z(e,"webhooks");return}o.envVars.length>0&&oe(e,{category:"Webhooks",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"WEBHOOKS_PROVIDER",o.id)}import Ke from"fs";import mt from"path";function Ic(e){return`import { brand } from "@nebutra/brand/metadata";
2658
2657
  import Link from "next/link";
2659
2658
 
2660
2659
  export default function WelcomePage() {
@@ -2764,21 +2763,21 @@ function Step({
2764
2763
  </li>
2765
2764
  );
2766
2765
  }
2767
- `}function Ac(e={}){return`
2766
+ `}function Cc(e={}){return`
2768
2767
  ## What you can do next
2769
2768
 
2770
2769
  ${[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(`
2771
2770
  `)}
2772
- `}function Ic(e=[]){return e.length===0?"":`
2771
+ `}function xc(e=[]){return e.length===0?"":`
2773
2772
  ## Production readiness holds
2774
2773
 
2775
- Do not enable these in production until you replace stubs, add provider credentials, and verify the integration contract:
2774
+ Do not enable these in production until provider credentials, adapter wiring, and the integration contract are verified:
2776
2775
 
2777
- ${e.map(n=>{let o=We(n.status);return`- ${n.flag}=${n.provider} ${o} \u2014 ${he(n.status)}`}).join(`
2776
+ ${e.map(n=>{let o=Xe(n.status);return`- ${n.flag}=${n.provider} ${o} \u2014 ${he(n.status)}`}).join(`
2778
2777
  `)}
2779
2778
 
2780
2779
  Review the package readiness matrix before handoff: [docs/package-status.md](docs/package-status.md)
2781
- `}function Cc(e,t,n=[],o={}){return`# Next steps \u2014 ${e}
2780
+ `}function Rc(e,t,n=[],o={}){return`# Next steps \u2014 ${e}
2782
2781
 
2783
2782
  Region: ${t}
2784
2783
 
@@ -2804,24 +2803,24 @@ Your AI-native SaaS scaffold is ready. Complete these four steps to go from temp
2804
2803
  \`\`\`
2805
2804
 
2806
2805
  After setup, delete the welcome route at \`apps/web/src/app/[locale]/welcome/\`.
2807
- ${Ac(o)}${Ic(n)}
2806
+ ${Cc(o)}${xc(n)}
2808
2807
 
2809
2808
  ## Resources
2810
2809
 
2811
2810
  - [Documentation](/docs)
2812
2811
  - [GitHub](https://github.com/nebutra/nebutra-sailor)
2813
2812
  - [Get free license (Individual/OPC)](https://nebutra.com/get-license)
2814
- `}async function ks(e,t){let{projectName:n,region:o,previewSelections:s=[],waveFeatures:r={}}=t;try{let i=ut.join(e,".sailor");Ve.existsSync(i)||Ve.mkdirSync(i,{recursive:!0}),Ve.writeFileSync(ut.join(i,"next-steps.md"),Cc(n,o,s,r))}catch(i){let a=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write .sailor/next-steps.md: ${a}`)}try{let i=ut.join(e,"apps","web");if(!Ve.existsSync(i))return;let a=ut.join(i,"src","app","[locale]","welcome");Ve.existsSync(a)||Ve.mkdirSync(a,{recursive:!0}),Ve.writeFileSync(ut.join(a,"page.tsx"),wc(n))}catch(i){let a=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write welcome page: ${a}`)}}function p(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2815
- `)}function Ts(e){return e!==null&&typeof e=="object"&&"code"in e&&e.code==="ENOENT"}function Rc(e,t){for(let n of t)if(e)p(!0,{event:"warn",step:n.flag,provider:n.provider,packageStatus:n.status,message:he(n.status)});else{let o=We(n.status);process.stdout.write(mt.yellow(`\u26A0 ${n.flag}=${n.provider} ${o} \u2014 ${he(n.status)}
2816
- `))}}function kc(e,t,n){let o=Ke.join(t,"packages/platform/db/prisma/schema.prisma"),s;try{s=Lt.readFileSync(o,"utf8")}catch(r){if(Ts(r)){p(e,{event:"step",step:"schema-prune",status:"skip"});return}let i=r instanceof Error?r.message:String(r);p(e,{event:"step",step:"schema-prune",status:"error",error:i});return}p(e,{event:"step",step:"schema-prune",status:"start"});try{let r=yn(s,n);Lt.writeFileSync(o,r),fn(Ke.join(Ke.dirname(o),"migrations"),n),p(e,{event:"step",step:"schema-prune",status:"ok"})}catch(r){let i=r instanceof Error?r.message:String(r);p(e,{event:"step",step:"schema-prune",status:"error",error:i})}}async function Ns(e){let{resolvedTarget:t,projectName:n,resolvedPm:o,opts:s,useJson:r,resolved:i,startedAt:a}=e,{region:c,orm:l,database:u,databaseHost:d,payment:_,paymentChoice:h,auth:f,socialLoginIds:E,aiProviders:S,deployTarget:m,docs:P,metering:G,billingMode:M,idp:ge,accessGate:pe,mcp:Z,waveToggles:j,previewSelections:K,config:C}=i,H={auth:f,payment:h,"billing-mode":M,idp:ge,template:"saas","access-gate":pe};p(r,{event:"step",step:"clone",status:"start"}),await Lo(t),p(r,{event:"step",step:"clone",status:"ok"}),p(r,{event:"step",step:"package",status:"start"}),await zo(t,n),p(r,{event:"step",step:"package",status:"ok"}),p(r,{event:"step",step:"config",status:"start"}),await co(t,C),p(r,{event:"step",step:"config",status:"ok"}),p(r,{event:"step",step:"governance-lints",status:"start"});let le=await Mo(t,C);p(r,{event:"step",step:"governance-lints",status:"ok",lints:le.lints}),p(r,{event:"step",step:"prune",status:"start"}),await cs(t,C),p(r,{event:"step",step:"prune",status:"ok"});{let v=Ke.join(t,"packages/platform/db/prisma/schema.prisma"),k;try{k=Lt.readFileSync(v,"utf-8")}catch(I){if(Ts(I))p(r,{event:"step",step:"schema-prune",status:"skip"});else{let x=I instanceof Error?I.message:String(I);p(r,{event:"step",step:"schema-prune",status:"error",error:x})}}if(k!==void 0){p(r,{event:"step",step:"schema-prune",status:"start"});try{let I=yn(k,H);Lt.writeFileSync(v,I),fn(Ke.join(Ke.dirname(v),"migrations"),H),p(r,{event:"step",step:"schema-prune",status:"ok"})}catch(I){let x=I instanceof Error?I.message:String(I);p(r,{event:"step",step:"schema-prune",status:"error",error:x})}}}if(p(r,{event:"step",step:"auth",choice:f,status:"start"}),await zn(t,f),p(r,{event:"step",step:"auth",choice:f,status:"ok"}),E.length>0?(p(r,{event:"step",step:"social-login",providers:E,status:"start"}),await Qn(t,E,f),p(r,{event:"step",step:"social-login",providers:E,status:"ok"})):p(r,{event:"step",step:"social-login",status:"skip"}),p(r,{event:"step",step:"db",choice:u,status:"start"}),await uo(t,u,n),u!=="none"){let v=st(d);v&&(await mo(t,v,n),p(r,{event:"step",step:"db-host",choice:d,status:"ok"}))}if(p(r,{event:"step",step:"db",choice:u,status:"ok"}),l==="drizzle"){p(r,{event:"step",step:"orm",choice:"drizzle",status:"start"});let v=await Zo(t,"drizzle",u);p(r,{event:"step",step:"orm",choice:"drizzle",status:v.applied?"ok":"skip",...v.reason?{reason:v.reason}:{}})}if(p(r,{event:"step",step:"payment",choice:h,status:"start"}),await ts(t,h),p(r,{event:"step",step:"payment",choice:h,status:"ok"}),await vo(t,i.email,c),r&&p(!0,{event:"step",step:"email",choice:i.email,status:"ok"}),await Cs(t,i.storage,c),r&&p(!0,{event:"step",step:"storage",choice:i.storage,status:"ok"}),await Ho(t,i.monitoring,c),r&&p(!0,{event:"step",step:"monitoring",choice:i.monitoring,status:"ok"}),await Wn(t,i.analytics,c),r&&p(!0,{event:"step",step:"analytics",choice:i.analytics,status:"ok"}),await Is(t,i.sms,c),r&&p(!0,{event:"step",step:"sms",choice:i.sms,status:"ok"}),await fs(t,i.queue,c),r&&p(!0,{event:"step",step:"queue",choice:i.queue,status:"ok"}),await Ps(t,i.search,c),r&&p(!0,{event:"step",step:"search",choice:i.search,status:"ok"}),await no(t,i.cache,c),r&&p(!0,{event:"step",step:"cache",choice:i.cache,status:"ok"}),await Xo(t,i.notifications,c),r&&p(!0,{event:"step",step:"notifications",choice:i.notifications,status:"ok"}),await Rs(t,i.webhooks,c),r&&p(!0,{event:"step",step:"webhooks",choice:i.webhooks,status:"ok"}),await io(t,i.cms,c),r&&p(!0,{event:"step",step:"cms",choice:i.cms,status:"ok"}),await Co(t,i.featureFlags,c),r&&p(!0,{event:"step",step:"feature-flags",choice:i.featureFlags,status:"ok"}),await so(t,i.captcha,c),r&&p(!0,{event:"step",step:"captcha",choice:i.captcha,status:"ok"}),await Ko(t,Z),r&&p(!0,{event:"step",step:"mcp",mode:Z,status:"ok"}),await Yo(t,G,_),r&&p(!0,{event:"step",step:"metering",mode:G,status:"ok"}),p(r,{event:"step",step:"prune-wave-features",status:"start"}),ps(t,j),p(r,{event:"step",step:"prune-wave-features",status:"ok",toggles:j}),C.orm==="prisma"&&C.database!=="none"?kc(r,t,H):p(r,{event:"step",step:"schema-prune",status:"skip"}),p(r,{event:"step",step:"billing-mode",choice:M,status:"ok"}),p(r,{event:"step",step:"idp",choice:ge,status:"ok"}),await ao(t,c),r&&p(!0,{event:"step",step:"compliance",region:c,status:"ok"}),await Ao(t),await ws(t,f),await ks(t,{projectName:n,region:c,previewSelections:K,waveFeatures:j}),C.aiMode!=="none"){p(r,{event:"step",step:"ai-providers",status:"start"});let v={providerIds:C.aiProviders,customEndpoint:C.customAiEndpoint},k=Ke.join(t,"packages/ai/ai-providers/templates");await is(t,v,k),p(r,{event:"step",step:"ai-providers",status:"ok"})}else p(r,{event:"step",step:"ai-providers",status:"skip"});p(r,{event:"step",step:"docs",status:"start"}),P!=="none"?(await yo(t,{framework:P,projectName:n}),p(r,{event:"step",step:"docs",framework:"fumadocs",requested:P,status:"ok"})):p(r,{event:"step",step:"docs",status:"skip"}),p(r,{event:"step",step:"deploy-target",status:"start"}),m!=="none"&&await Vn(t,m),await Bn(t,C.deployTargets),p(r,{event:"step",step:"deploy-target",status:"ok",targets:C.deployTargets});let w={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""};p(r,{event:"step",step:"env",status:"start"}),await _o(t,w),p(r,{event:"step",step:"env",status:"ok"}),p(r,{event:"step",step:"scaffold-extras",status:"start"});let fe=await Ss(t,{projectName:n,withWorkflows:!!s.withWorkflows,withPythonBackend:!!s.withPythonBackend});p(r,{event:"step",step:"scaffold-extras",status:"ok",applied:fe.applied,skipped:fe.skipped}),p(r,{event:"step",step:"license",status:"start"});try{let v=Vo(t,{projectName:n,cliVersion:X});p(r,{event:"step",step:"license",status:"ok",tier:"independent",wrote:v.wrote}),r||process.stdout.write(mt.dim(` License: Nebutra-Sailor Independent Developer License (free for \u2264 1 FTE, < $1M ARR).
2813
+ `}async function kr(e,t){let{projectName:n,region:o,previewSelections:r=[],waveFeatures:s={}}=t;try{let i=mt.join(e,".sailor");Ke.existsSync(i)||Ke.mkdirSync(i,{recursive:!0}),Ke.writeFileSync(mt.join(i,"next-steps.md"),Rc(n,o,r,s))}catch(i){let a=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write .sailor/next-steps.md: ${a}`)}try{let i=mt.join(e,"apps","web");if(!Ke.existsSync(i))return;let a=mt.join(i,"src","app","[locale]","welcome");Ke.existsSync(a)||Ke.mkdirSync(a,{recursive:!0}),Ke.writeFileSync(mt.join(a,"page.tsx"),Ic(n))}catch(i){let a=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write welcome page: ${a}`)}}function l(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2814
+ `)}function Tr(e){return e!==null&&typeof e=="object"&&"code"in e&&e.code==="ENOENT"}function Tc(e,t){for(let n of t)if(e)l(!0,{event:"warn",step:n.flag,provider:n.provider,packageStatus:n.status,message:he(n.status)});else{let o=Xe(n.status);process.stdout.write(gt.yellow(`\u26A0 ${n.flag}=${n.provider} ${o} \u2014 ${he(n.status)}
2815
+ `))}}function Nc(e,t,n){let o=$e.join(t,"packages/platform/db/prisma/schema.prisma"),r;try{r=Lt.readFileSync(o,"utf8")}catch(s){if(Tr(s)){l(e,{event:"step",step:"schema-prune",status:"skip"});return}let i=s instanceof Error?s.message:String(s);l(e,{event:"step",step:"schema-prune",status:"error",error:i});return}l(e,{event:"step",step:"schema-prune",status:"start"});try{let s=yn(r,n);Lt.writeFileSync(o,s),fn($e.join($e.dirname(o),"migrations"),n),l(e,{event:"step",step:"schema-prune",status:"ok"})}catch(s){let i=s instanceof Error?s.message:String(s);l(e,{event:"step",step:"schema-prune",status:"error",error:i})}}async function Nr(e){let{resolvedTarget:t,projectName:n,resolvedPm:o,opts:r,useJson:s,resolved:i,startedAt:a}=e,{region:c,orm:p,database:u,databaseHost:d,payment:_,paymentChoice:h,auth:f,socialLoginIds:E,aiProviders:S,deployTarget:m,docs:P,metering:G,billingMode:M,idp:ge,accessGate:pe,mcp:Z,waveToggles:j,previewSelections:K,config:C}=i,H={auth:f,payment:h,"billing-mode":M,idp:ge,template:"saas","access-gate":pe};l(s,{event:"step",step:"clone",status:"start"}),await Lo(t),l(s,{event:"step",step:"clone",status:"ok"}),l(s,{event:"step",step:"package",status:"start"}),await zo(t,n),l(s,{event:"step",step:"package",status:"ok"}),l(s,{event:"step",step:"config",status:"start"}),await co(t,C),l(s,{event:"step",step:"config",status:"ok"}),l(s,{event:"step",step:"governance-lints",status:"start"});let le=await Mo(t,C);l(s,{event:"step",step:"governance-lints",status:"ok",lints:le.lints}),l(s,{event:"step",step:"prune",status:"start"}),await cr(t,C),l(s,{event:"step",step:"prune",status:"ok"});{let v=$e.join(t,"packages/platform/db/prisma/schema.prisma"),k;try{k=Lt.readFileSync(v,"utf-8")}catch(I){if(Tr(I))l(s,{event:"step",step:"schema-prune",status:"skip"});else{let x=I instanceof Error?I.message:String(I);l(s,{event:"step",step:"schema-prune",status:"error",error:x})}}if(k!==void 0){l(s,{event:"step",step:"schema-prune",status:"start"});try{let I=yn(k,H);Lt.writeFileSync(v,I),fn($e.join($e.dirname(v),"migrations"),H),l(s,{event:"step",step:"schema-prune",status:"ok"})}catch(I){let x=I instanceof Error?I.message:String(I);l(s,{event:"step",step:"schema-prune",status:"error",error:x})}}}if(l(s,{event:"step",step:"auth",choice:f,status:"start"}),await zn(t,f),l(s,{event:"step",step:"auth",choice:f,status:"ok"}),E.length>0?(l(s,{event:"step",step:"social-login",providers:E,status:"start"}),await Qn(t,E,f),l(s,{event:"step",step:"social-login",providers:E,status:"ok"})):l(s,{event:"step",step:"social-login",status:"skip"}),l(s,{event:"step",step:"db",choice:u,status:"start"}),await uo(t,u,n),u!=="none"){let v=st(d);v&&(await mo(t,v,n),l(s,{event:"step",step:"db-host",choice:d,status:"ok"}))}if(l(s,{event:"step",step:"db",choice:u,status:"ok"}),p==="drizzle"){l(s,{event:"step",step:"orm",choice:"drizzle",status:"start"});let v=await Zo(t,"drizzle",u);l(s,{event:"step",step:"orm",choice:"drizzle",status:v.applied?"ok":"skip",...v.reason?{reason:v.reason}:{}})}if(l(s,{event:"step",step:"payment",choice:h,status:"start"}),await tr(t,h),l(s,{event:"step",step:"payment",choice:h,status:"ok"}),await vo(t,i.email,c),s&&l(!0,{event:"step",step:"email",choice:i.email,status:"ok"}),await Cr(t,i.storage,c),s&&l(!0,{event:"step",step:"storage",choice:i.storage,status:"ok"}),await Ho(t,i.monitoring,c),s&&l(!0,{event:"step",step:"monitoring",choice:i.monitoring,status:"ok"}),await Wn(t,i.analytics,c),s&&l(!0,{event:"step",step:"analytics",choice:i.analytics,status:"ok"}),await Ir(t,i.sms,c),s&&l(!0,{event:"step",step:"sms",choice:i.sms,status:"ok"}),await fr(t,i.queue,c),s&&l(!0,{event:"step",step:"queue",choice:i.queue,status:"ok"}),await Pr(t,i.search,c),s&&l(!0,{event:"step",step:"search",choice:i.search,status:"ok"}),await no(t,i.cache,c),s&&l(!0,{event:"step",step:"cache",choice:i.cache,status:"ok"}),await Xo(t,i.notifications,c),s&&l(!0,{event:"step",step:"notifications",choice:i.notifications,status:"ok"}),await Rr(t,i.webhooks,c),s&&l(!0,{event:"step",step:"webhooks",choice:i.webhooks,status:"ok"}),await io(t,i.cms,c),s&&l(!0,{event:"step",step:"cms",choice:i.cms,status:"ok"}),await Co(t,i.featureFlags,c),s&&l(!0,{event:"step",step:"feature-flags",choice:i.featureFlags,status:"ok"}),await ro(t,i.captcha,c),s&&l(!0,{event:"step",step:"captcha",choice:i.captcha,status:"ok"}),await Ko(t,Z),s&&l(!0,{event:"step",step:"mcp",mode:Z,status:"ok"}),await Yo(t,G,_),s&&l(!0,{event:"step",step:"metering",mode:G,status:"ok"}),l(s,{event:"step",step:"prune-wave-features",status:"start"}),pr(t,j),l(s,{event:"step",step:"prune-wave-features",status:"ok",toggles:j}),C.orm==="prisma"&&C.database!=="none"?Nc(s,t,H):l(s,{event:"step",step:"schema-prune",status:"skip"}),l(s,{event:"step",step:"billing-mode",choice:M,status:"ok"}),l(s,{event:"step",step:"idp",choice:ge,status:"ok"}),await ao(t,c),s&&l(!0,{event:"step",step:"compliance",region:c,status:"ok"}),await Ao(t),await wr(t,f),await kr(t,{projectName:n,region:c,previewSelections:K,waveFeatures:j}),C.aiMode!=="none"){l(s,{event:"step",step:"ai-providers",status:"start"});let v={providerIds:C.aiProviders,customEndpoint:C.customAiEndpoint},k=$e.join(t,"packages/ai/ai-providers/templates");await ir(t,v,k),l(s,{event:"step",step:"ai-providers",status:"ok"})}else l(s,{event:"step",step:"ai-providers",status:"skip"});l(s,{event:"step",step:"docs",status:"start"}),P!=="none"?(await yo(t,{framework:P,projectName:n}),l(s,{event:"step",step:"docs",framework:"fumadocs",requested:P,status:"ok"})):l(s,{event:"step",step:"docs",status:"skip"}),l(s,{event:"step",step:"deploy-target",status:"start"}),m!=="none"&&await Vn(t,m),await Bn(t,C.deployTargets),l(s,{event:"step",step:"deploy-target",status:"ok",targets:C.deployTargets});let w={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""};l(s,{event:"step",step:"env",status:"start"}),await _o(t,w),l(s,{event:"step",step:"env",status:"ok"}),l(s,{event:"step",step:"scaffold-extras",status:"start"});let fe=await Sr(t,{projectName:n,withWorkflows:!!r.withWorkflows,withPythonBackend:!!r.withPythonBackend});l(s,{event:"step",step:"scaffold-extras",status:"ok",applied:fe.applied,skipped:fe.skipped}),l(s,{event:"step",step:"license",status:"start"});try{let v=Vo(t,{projectName:n,cliVersion:X});l(s,{event:"step",step:"license",status:"ok",tier:"independent",wrote:v.wrote}),s||process.stdout.write(gt.dim(` License: Nebutra-Sailor Independent Developer License (free for \u2264 1 FTE, < $1M ARR).
2817
2816
  Upstream AGPL preserved as LICENSE-AGPL-REFERENCE.md.
2818
- `))}catch(v){p(r,{event:"step",step:"license",status:"warn",message:v instanceof Error?v.message:String(v)})}if(s.install!==!1){let v=o==="bun"?"bun":o,k=["install"];r?p(!0,{event:"step",step:"install",pm:o,status:"start"}):process.stdout.write(mt.dim(` Installing dependencies with ${o}\u2026
2819
- `));try{Ot(v,k,{cwd:t,stdio:r?"ignore":"inherit"}),p(r,{event:"step",step:"install",status:"ok"})}catch(I){let x=I instanceof Error?I.message:String(I);r?p(!0,{event:"step",step:"install",status:"error",error:x}):process.stdout.write(mt.yellow(` \u26A0 install failed \u2014 run '${o} install' manually.
2820
- `))}}else p(r,{event:"step",step:"install",status:"skip"});if(s.git!==!1){r&&p(!0,{event:"step",step:"git-init",status:"start"});try{Ot("git",["init","-q"],{cwd:t,stdio:"ignore"}),Ot("git",["add","-A"],{cwd:t,stdio:"ignore"}),Ot("git",["-c","user.email=you@example.com","-c","user.name=You","commit","-q","-m","chore: initial scaffold from create-sailor"],{cwd:t,stdio:"ignore"}),p(r,{event:"step",step:"git-init",status:"ok"})}catch(v){let k=v instanceof Error?v.message:String(v);r?p(!0,{event:"step",step:"git-init",status:"error",error:k}):process.stdout.write(mt.yellow(` \u26A0 git init skipped \u2014 not fatal.
2821
- `))}}else p(r,{event:"step",step:"git-init",status:"skip"});let ye=Math.max(1,Math.round((Date.now()-a)/1e3));Xn({template_version:X,package_manager:o,region:c,auth:f,payment:h,ai_providers:S,deploy_target:m,duration_ms:Date.now()-a}),K.length>0&&Rc(r,K),r?p(!0,{event:"done",status:"ok",elapsedSec:ye,targetDir:t,previewSelections:K,waveFeatures:j}):qn({elapsedSec:ye,targetDir:t,skippedInstall:s.install===!1,previewSelections:K,waveFeatures:j});try{xc({pkg:{name:"create-sailor",version:X},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}}import Tc from"cfonts";import Nc from"picocolors";function Os(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${X}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
2822
- `));return}Tc.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(Nc.dim(` AI-Native SaaS Template \xB7 v${X} \xB7 nebutra.com
2817
+ `))}catch(v){l(s,{event:"step",step:"license",status:"warn",message:v instanceof Error?v.message:String(v)})}if(r.install!==!1){let v=o==="bun"?"bun":o,k=["install"];s?l(!0,{event:"step",step:"install",pm:o,status:"start"}):process.stdout.write(gt.dim(` Installing dependencies with ${o}\u2026
2818
+ `));try{Ot(v,k,{cwd:t,stdio:s?"ignore":"inherit"}),l(s,{event:"step",step:"install",status:"ok"})}catch(I){let x=I instanceof Error?I.message:String(I);s?l(!0,{event:"step",step:"install",status:"error",error:x}):process.stdout.write(gt.yellow(` \u26A0 install failed \u2014 run '${o} install' manually.
2819
+ `))}}else l(s,{event:"step",step:"install",status:"skip"});if(r.git!==!1){s&&l(!0,{event:"step",step:"git-init",status:"start"});try{Ot("git",["init","-q"],{cwd:t,stdio:"ignore"}),Ot("git",["add","-A"],{cwd:t,stdio:"ignore"}),Ot("git",["-c","user.email=you@example.com","-c","user.name=You","commit","-q","-m","chore: initial scaffold from create-sailor"],{cwd:t,stdio:"ignore"}),l(s,{event:"step",step:"git-init",status:"ok"})}catch(v){let k=v instanceof Error?v.message:String(v);s?l(!0,{event:"step",step:"git-init",status:"error",error:k}):process.stdout.write(gt.yellow(` \u26A0 git init skipped \u2014 not fatal.
2820
+ `))}}else l(s,{event:"step",step:"git-init",status:"skip"});let ye=Math.max(1,Math.round((Date.now()-a)/1e3));Xn({template_version:X,package_manager:o,region:c,auth:f,payment:h,ai_providers:S,deploy_target:m,duration_ms:Date.now()-a}),K.length>0&&Tc(s,K),s?l(!0,{event:"done",status:"ok",elapsedSec:ye,targetDir:t,previewSelections:K,waveFeatures:j}):qn({elapsedSec:ye,targetDir:t,skippedInstall:r.install===!1,previewSelections:K,waveFeatures:j});try{kc({pkg:{name:"create-sailor",version:X},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}}import Oc from"cfonts";import Lc from"picocolors";function Or(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${X}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
2821
+ `));return}Oc.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(Lc.dim(` AI-Native SaaS Template \xB7 v${X} \xB7 nebutra.com
2823
2822
 
2824
- `))}var Oc=`Usage: create-sailor [name] [options]
2823
+ `))}var Uc=`Usage: create-sailor [name] [options]
2825
2824
 
2826
2825
  Arguments:
2827
2826
  name project directory (default: ./my-saas-app)
@@ -2856,17 +2855,17 @@ Feature flags (region-based smart defaults):
2856
2855
  --queue <id> qstash | bullmq | upstash | sqs | none [Foundation]
2857
2856
  --search <id> meilisearch | typesense | algolia | pgvector | none [Foundation]
2858
2857
  --cache <id> upstash-redis | vercel-kv | redis | dragonfly | none
2859
- --notifications <id> novu | knock | custom | none [Foundation]
2860
- --webhooks <id> svix | custom | none [Foundation]
2858
+ --notifications <id> novu | knock | custom | none
2859
+ --webhooks <id> svix | custom | none
2861
2860
  --cms <id> sanity | contentful | strapi | none
2862
- --feature-flags <id> vercel-flags | growthbook | configcat | none [WIP]
2861
+ --feature-flags <id> vercel-flags | growthbook | configcat | none [Foundation]
2863
2862
  --captcha <id> turnstile | hcaptcha | aliyun-slide | none [WIP]
2864
2863
  --billing-mode <mode> usage | seat | credits (default: usage)
2865
2864
  --idp <id> clerk | oauth-server (default: clerk)
2866
2865
  --access-gate <mode> none | invite (default: none)
2867
2866
 
2868
2867
  Preview statuses:
2869
- [Foundation] \u2014 types + factory complete; adapters need external credentials & may not work out-of-the-box
2868
+ [Foundation] \u2014 core path works; provider credentials, adapter wiring, or integration verification still required
2870
2869
  [WIP] \u2014 actively being built; do not use in production
2871
2870
  See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md
2872
2871
 
@@ -2892,10 +2891,10 @@ Examples:
2892
2891
  $ npx create-sailor@latest my-app --region=cn --auth=clerk
2893
2892
  $ npx create-sailor@latest my-app --region=hybrid --ai=openai,deepseek
2894
2893
  $ npm create sailor@latest --dry-run --region=cn
2895
- `;function Ls(){process.stdout.write(Oc)}import Ut from"picocolors";function Us(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Lc(e){let t=Us()?"\u25B8":"->",n=`[${e.index}/${e.total}]`,o=e.label.padEnd(18," ");return Us()?`${Ut.dim(n)} ${Ut.bold(o)} ${Ut.dim(t)} ${Ut.cyan(e.value)}`:`${n} ${o} ${t} ${e.value}`}function Ms(e){process.stdout.write(Lc(e)+`
2896
- `)}import{existsSync as Uc,mkdirSync as Ds,writeFileSync as Fs}from"fs";import{homedir as js,platform as Mc}from"os";import{join as gt}from"path";function Dc(){if(Mc()==="win32"){let t=process.env.LOCALAPPDATA||gt(js(),"AppData","Local");return gt(t,"nebutra")}let e=process.env.XDG_CONFIG_HOME;return e?gt(e,"nebutra"):gt(js(),".config","nebutra")}function Fc(){let e=process.env.NEBUTRA_TELEMETRY;return e==="0"||e==="false"||e==="no"}function Bs(){if(!process.stderr.isTTY||!process.stdin.isTTY||process.env.CI)return;let e=Dc(),t=gt(e,"first-run-acked");try{if(Uc(t))return}catch{return}if(Fc()){try{Ds(e,{recursive:!0}),Fs(t,"")}catch{}return}let n=["[36m\u2139[0m Nebutra collects anonymous usage analytics to improve the scaffolder."," Opt out at any time: export NEBUTRA_TELEMETRY=0"," Privacy policy: https://nebutra.com/legal/cli-analytics",""];try{process.stderr.write(n.join(`
2897
- `))}catch{}try{Ds(e,{recursive:!0}),Fs(t,"")}catch{}}function $e(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2898
- `)}function Bc(e,t,n,o,s){let{region:r,orm:i,database:a,paymentChoice:c,docs:l,socialLoginIds:u,aiMode:d,aiProviders:_,customAiEndpoint:h,deployTarget:f,metering:E,payment:S,billingMode:m,idp:P,mcp:G,waveToggles:M,previewSelections:ge}=t,{email:pe,storage:Z,monitoring:j,analytics:K,sms:C,queue:H,search:le,cache:w,notifications:fe,webhooks:Ye,cms:qe,featureFlags:ye,captcha:v}=t,k=_.length,I=[`clone template \u2192 ${n}`,"write nebutra.config.json",`governance-lints \u2192 write governance.config.json + wire pnpm lint (no-raw-inputs${a!=="none"?" + repository-seam":""})`,`prune template (orm=${i}, i18n=${t.i18n})`,`region \u2192 ${r}`,`auth \u2192 ${t.auth==="none"?"skip (remove packages/auth)":`configure ${t.auth}`}`,...u.length>0?[`social-login \u2192 generate ${u.length} callback route${u.length===1?"":"s"} + SocialLoginButtons.tsx (${u.join(", ")})`]:[],`db \u2192 ${a==="none"?"skip (remove packages/db)":`configure Prisma for ${a}`}`,`payment \u2192 ${c==="none"?"skip (remove packages/billing)":`configure ${c}`}`,...l!=="none"?[`docs \u2192 scaffold apps/docs (${l==="fumadocs"?"fumadocs":`${l} \u2192 fumadocs fallback`})`]:[],...k>0||h?[`ai-providers \u2192 generate ${d} registry seed + env (${k}${h?" + custom":""} provider${k===1&&!h?"":"s"})`]:[],...pe!=="none"?[`email \u2192 configure ${pe}`]:[],...Z!=="none"?[`storage \u2192 configure ${Z}`]:[],...j!=="none"?[`monitoring \u2192 configure ${j}`]:[],...K!=="none"?[`analytics \u2192 configure ${K}`]:[],...C!=="none"?[`sms \u2192 configure ${C}`]:[],...H!=="none"?[`queue \u2192 configure ${H}`]:[],...le!=="none"?[`search \u2192 configure ${le}`]:[],...w!=="none"?[`cache \u2192 configure ${w}`]:[],...fe!=="none"?[`notifications \u2192 configure ${fe}`]:[],...Ye!=="none"?[`webhooks \u2192 configure ${Ye}`]:[],...qe!=="none"?[`cms \u2192 configure ${qe}`]:[],...ye!=="none"?[`feature-flags \u2192 configure ${ye}`]:[],...v!=="none"?[`captcha \u2192 configure ${v}`]:[],`mcp \u2192 ${G==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${E==="off"?"disabled":E==="auto"?S!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...m!=="usage"?[`billing-mode \u2192 ${m}`]:[],...P!=="clerk"?[`idp \u2192 ${P}`]:[],`cron-jobs \u2192 ${M.cronJobs?"enabled":"disabled"}`,`audit-log \u2192 ${M.auditLog?"enabled":"disabled"}`,`api-keys \u2192 ${M.apiKeys?"enabled":"disabled"}`,`command-palette \u2192 ${M.commandPalette?"enabled":"disabled"}`,`cookie-consent \u2192 ${M.cookieConsent?"enabled":"disabled"}`,`legal-pages \u2192 ${M.legalPages?"enabled":"disabled"}`,`china-compliance \u2192 ${M.chinaCompliance?"enabled (@nebutra/china-compliance + ICP footer)":"disabled"}`,`compliance \u2192 inject ${r} 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)",...f!=="none"?[`deploy \u2192 inject ${f} config`]:[],"inject .env.local",s.install===!1?"skip install":`run ${o} install`,s.git===!1?"skip git init":"run git init"];if(e){for(let x of I)$e(!0,{event:"plan",action:x});for(let x of ge)$e(!0,{event:"warn",step:x.flag,provider:x.provider,packageStatus:x.status});$e(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2894
+ `;function Lr(){process.stdout.write(Uc)}import Ut from"picocolors";function Ur(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Mc(e){let t=Ur()?"\u25B8":"->",n=`[${e.index}/${e.total}]`,o=e.label.padEnd(18," ");return Ur()?`${Ut.dim(n)} ${Ut.bold(o)} ${Ut.dim(t)} ${Ut.cyan(e.value)}`:`${n} ${o} ${t} ${e.value}`}function Mr(e){process.stdout.write(Mc(e)+`
2895
+ `)}import{existsSync as Dc,mkdirSync as Dr,writeFileSync as Fr}from"fs";import{homedir as jr,platform as Fc}from"os";import{join as ft}from"path";function jc(){if(Fc()==="win32"){let t=process.env.LOCALAPPDATA||ft(jr(),"AppData","Local");return ft(t,"nebutra")}let e=process.env.XDG_CONFIG_HOME;return e?ft(e,"nebutra"):ft(jr(),".config","nebutra")}function Bc(){let e=process.env.NEBUTRA_TELEMETRY;return e==="0"||e==="false"||e==="no"}function Br(){if(!process.stderr.isTTY||!process.stdin.isTTY||process.env.CI)return;let e=jc(),t=ft(e,"first-run-acked");try{if(Dc(t))return}catch{return}if(Bc()){try{Dr(e,{recursive:!0}),Fr(t,"")}catch{}return}let n=["[36m\u2139[0m Nebutra collects anonymous usage analytics to improve the scaffolder."," Opt out at any time: export NEBUTRA_TELEMETRY=0"," Privacy policy: https://nebutra.com/legal/cli-analytics",""];try{process.stderr.write(n.join(`
2896
+ `))}catch{}try{Dr(e,{recursive:!0}),Fr(t,"")}catch{}}function Ye(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2897
+ `)}function Kc(e,t,n,o,r){let{region:s,orm:i,database:a,paymentChoice:c,docs:p,socialLoginIds:u,aiMode:d,aiProviders:_,customAiEndpoint:h,deployTarget:f,metering:E,payment:S,billingMode:m,idp:P,mcp:G,waveToggles:M,previewSelections:ge}=t,{email:pe,storage:Z,monitoring:j,analytics:K,sms:C,queue:H,search:le,cache:w,notifications:fe,webhooks:qe,cms:Ge,featureFlags:ye,captcha:v}=t,k=_.length,I=[`clone template \u2192 ${n}`,"write nebutra.config.json",`governance-lints \u2192 write governance.config.json + wire pnpm lint (no-raw-inputs${a!=="none"?" + repository-seam":""})`,`prune template (orm=${i}, i18n=${t.i18n})`,`region \u2192 ${s}`,`auth \u2192 ${t.auth==="none"?"skip (remove packages/auth)":`configure ${t.auth}`}`,...u.length>0?[`social-login \u2192 generate ${u.length} callback route${u.length===1?"":"s"} + SocialLoginButtons.tsx (${u.join(", ")})`]:[],`db \u2192 ${a==="none"?"skip (remove packages/db)":`configure Prisma for ${a}`}`,...a!=="none"?[`db-host \u2192 configure ${t.databaseHost}`]:[],`payment \u2192 ${c==="none"?"skip (remove packages/billing)":`configure ${c}`}`,...p!=="none"?[`docs \u2192 scaffold apps/docs (${p==="fumadocs"?"fumadocs":`${p} \u2192 fumadocs fallback`})`]:[],...k>0||h?[`ai-providers \u2192 generate ${d} registry seed + env (${k}${h?" + custom":""} provider${k===1&&!h?"":"s"})`]:[],...pe!=="none"?[`email \u2192 configure ${pe}`]:[],...Z!=="none"?[`storage \u2192 configure ${Z}`]:[],...j!=="none"?[`monitoring \u2192 configure ${j}`]:[],...K!=="none"?[`analytics \u2192 configure ${K}`]:[],...C!=="none"?[`sms \u2192 configure ${C}`]:[],...H!=="none"?[`queue \u2192 configure ${H}`]:[],...le!=="none"?[`search \u2192 configure ${le}`]:[],...w!=="none"?[`cache \u2192 configure ${w}`]:[],...fe!=="none"?[`notifications \u2192 configure ${fe}`]:[],...qe!=="none"?[`webhooks \u2192 configure ${qe}`]:[],...Ge!=="none"?[`cms \u2192 configure ${Ge}`]:[],...ye!=="none"?[`feature-flags \u2192 configure ${ye}`]:[],...v!=="none"?[`captcha \u2192 configure ${v}`]:[],`mcp \u2192 ${G==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${E==="off"?"disabled":E==="auto"?S!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...m!=="usage"?[`billing-mode \u2192 ${m}`]:[],...P!=="clerk"?[`idp \u2192 ${P}`]:[],`cron-jobs \u2192 ${M.cronJobs?"enabled":"disabled"}`,`audit-log \u2192 ${M.auditLog?"enabled":"disabled"}`,`api-keys \u2192 ${M.apiKeys?"enabled":"disabled"}`,`command-palette \u2192 ${M.commandPalette?"enabled":"disabled"}`,`cookie-consent \u2192 ${M.cookieConsent?"enabled":"disabled"}`,`legal-pages \u2192 ${M.legalPages?"enabled":"disabled"}`,`china-compliance \u2192 ${M.chinaCompliance?"enabled (@nebutra/china-compliance + ICP footer)":"disabled"}`,`compliance \u2192 inject ${s} 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)",...f!=="none"?[`deploy \u2192 inject ${f} config`]:[],"inject .env.local",r.install===!1?"skip install":`run ${o} install`,r.git===!1?"skip git init":"run git init"];if(e){for(let x of I)Ye(!0,{event:"plan",action:x});for(let x of ge)Ye(!0,{event:"warn",step:x.flag,provider:x.provider,packageStatus:x.status});Ye(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2899
2898
  `+F.bold(`Dry run \u2014 planned actions:
2900
2899
  `));for(let x of I)process.stdout.write(` \u2022 ${x}
2901
2900
  `);if(ge.length>0){process.stdout.write(`
@@ -2903,7 +2902,7 @@ Examples:
2903
2902
  `)));for(let x of ge)process.stdout.write(F.yellow(`\u26A0 ${x.flag}=${x.provider}
2904
2903
  `))}process.stdout.write(F.dim(`
2905
2904
  No files were written.
2906
- `))}}async function Vc(){let e=Cn();e.parse(process.argv);let t=e.opts(),[n]=e.args;t.help&&(Ls(),process.exit(0));let o=!!t.json,s=!!t.dryRun,r=!!t.yes,i=r||!process.stdin.isTTY;if(o||(Bs(),Os()),$e(o,{event:"start",version:X}),!t.pm)try{jc("pnpm --version",{stdio:"ignore"})}catch{o||process.stderr.write(`
2905
+ `))}}async function $c(){let e=Cn();e.parse(process.argv);let t=e.opts(),[n]=e.args;t.help&&(Lr(),process.exit(0));let o=!!t.json,r=!!t.dryRun,s=!!t.yes,i=s||!process.stdin.isTTY;if(o||(Br(),Or()),Ye(o,{event:"start",version:X}),!t.pm)try{Vc("pnpm --version",{stdio:"ignore"})}catch{o||process.stderr.write(`
2907
2906
  ${F.red("\u2718")} ${F.bold("pnpm is required")} but was not found on PATH.
2908
2907
 
2909
2908
  The scaffold uses pnpm workspaces + Turborepo. Install pnpm first:
@@ -2912,11 +2911,11 @@ The scaffold uses pnpm workspaces + Turborepo. Install pnpm first:
2912
2911
  Then retry: ${F.cyan("pnpm dlx create-sailor@latest")}
2913
2912
  (or pass ${F.dim("--pm=npm")} if you know workspace:* won't resolve in your setup)
2914
2913
 
2915
- `),$e(o,{event:"error",code:"PNPM_MISSING"}),process.exit(1)}let a=n??(r?"./my-saas-app":void 0),c;if(a)c=a;else if(i)c="./my-saas-app";else{let f=await nt.group({name:()=>nt.text({message:"Where should we create your project?",placeholder:"./my-saas-app",defaultValue:"./my-saas-app",validate:E=>{if(!E?.length)return"Please enter a path."}})},{onCancel:()=>{process.stdout.write(F.red(`\u2718 Cancelled
2916
- `)),process.exit(130)}});c=String(f.name)}let l=Ks.basename(Ks.resolve(c)),u=t.pm??Nn(),d=await Yn(t,o),_=[["Project name",l],["Region",d.region],["Auth",d.auth],["Social login",d.socialLoginIds.length>0?d.socialLoginIds.map(f=>He.find(E=>E.id===f)?.name??f).join(", "):"none"],["ORM",d.orm],["Database",d.database],["Payment",d.paymentChoice],["AI topology",`${d.aiMode}${d.aiProviders.length>0?` (${d.aiProviders.join(", ")} seed)`:""}${d.customAiEndpoint?" + custom endpoint":""}`],["Email",d.email],["Storage",d.storage],["Monitoring",d.monitoring],["Analytics",d.analytics],["SMS",d.sms],["Deploy Target",d.deployTarget],["Docs Framework",d.docs],["Access gate",d.accessGate]];o?_.forEach(([f,E],S)=>{$e(!0,{event:"step",step:f,value:E,index:S+1,total:_.length})}):_.forEach(([f,E],S)=>{Ms({index:S+1,total:_.length,label:f,value:E})}),s&&(Bc(o,d,c,u,t),process.exit(0));let h=async()=>{process.stdout.write(`
2914
+ `),Ye(o,{event:"error",code:"PNPM_MISSING"}),process.exit(1)}let a=n??(s?"./my-saas-app":void 0),c;if(a)c=a;else if(i)c="./my-saas-app";else{let f=await ot.group({name:()=>ot.text({message:"Where should we create your project?",placeholder:"./my-saas-app",defaultValue:"./my-saas-app",validate:E=>{if(!E?.length)return"Please enter a path."}})},{onCancel:()=>{process.stdout.write(F.red(`\u2718 Cancelled
2915
+ `)),process.exit(130)}});c=String(f.name)}let p=Kr.basename(Kr.resolve(c)),u=t.pm??Nn(),d=await Yn(t,o),_=[["Project name",p],["Region",d.region],["Auth",d.auth],["Social login",d.socialLoginIds.length>0?d.socialLoginIds.map(f=>We.find(E=>E.id===f)?.name??f).join(", "):"none"],["ORM",d.orm],["Database",d.database],["Database Host",d.databaseHost],["Payment",d.paymentChoice],["AI topology",`${d.aiMode}${d.aiProviders.length>0?` (${d.aiProviders.join(", ")} seed)`:""}${d.customAiEndpoint?" + custom endpoint":""}`],["Email",d.email],["Storage",d.storage],["Monitoring",d.monitoring],["Analytics",d.analytics],["SMS",d.sms],["Deploy Target",d.deployTarget],["Docs Framework",d.docs],["Access gate",d.accessGate]];o?_.forEach(([f,E],S)=>{Ye(!0,{event:"step",step:f,value:E,index:S+1,total:_.length})}):_.forEach(([f,E],S)=>{Mr({index:S+1,total:_.length,label:f,value:E})}),r&&(Kc(o,d,c,u,t),process.exit(0));let h=async()=>{process.stdout.write(`
2917
2916
  `+F.red(`\u2718 Cancelled
2918
- `)),Vs.existsSync(c)&&await nt.confirm({message:`Cleanup partial install at ${c}?`,initialValue:!0})===!0&&(Vs.rmSync(c,{recursive:!0,force:!0}),process.stdout.write(F.dim(` \u2713 Removed ${c}
2919
- `))),process.exit(130)};process.on("SIGINT",h);try{await Ns({resolvedTarget:c,projectName:l,resolvedPm:u,opts:t,useJson:o,resolved:d,startedAt:Date.now()}),process.exit(0)}catch(f){let E=f instanceof Error?f.message:String(f);o?$e(!0,{event:"error",message:E}):process.stdout.write(F.red(`
2917
+ `)),Vr.existsSync(c)&&await ot.confirm({message:`Cleanup partial install at ${c}?`,initialValue:!0})===!0&&(Vr.rmSync(c,{recursive:!0,force:!0}),process.stdout.write(F.dim(` \u2713 Removed ${c}
2918
+ `))),process.exit(130)};process.on("SIGINT",h);try{await Nr({resolvedTarget:c,projectName:p,resolvedPm:u,opts:t,useJson:o,resolved:d,startedAt:Date.now()}),process.exit(0)}catch(f){let E=f instanceof Error?f.message:String(f);o?Ye(!0,{event:"error",message:E}):process.stdout.write(F.red(`
2920
2919
  \u2718 Failed: ${E}
2921
- `)),process.exit(1)}}Vc().catch(e=>{process.stderr.write(String(e)+`
2920
+ `)),process.exit(1)}}$c().catch(e=>{process.stderr.write(String(e)+`
2922
2921
  `),process.exit(1)});