create-sailor 1.8.1 → 1.8.3

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 (63) hide show
  1. package/LICENSE +21 -676
  2. package/README.md +3 -3
  3. package/dist/aws-kms-3GX7ZOSJ.js +1 -0
  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-JTXBZ2SU.js +1 -0
  8. package/dist/{chunk-M3QJPQWS.js → chunk-KRX2KWWT.js} +1 -1
  9. package/dist/chunk-OIQB5F6Y.js +1 -0
  10. package/dist/chunk-P2WEIQRQ.js +3 -0
  11. package/dist/chunk-RH2FFVSB.js +1 -0
  12. package/dist/chunk-STX7THHW.js +21 -0
  13. package/dist/chunk-TW5BOTVX.js +0 -0
  14. package/dist/chunk-VFREGXHN.js +1 -0
  15. package/dist/chunk-W5TBFCWY.js +4 -0
  16. package/dist/chunk-WJLTO7JW.js +0 -0
  17. package/dist/chunk-WU3IV4WF.js +1 -0
  18. package/dist/{credits-RR7B3C4K.js → credits-HWAYRMKF.js} +31 -31
  19. package/dist/{dist-NJH3URWV.js → dist-SFI2IGZ2.js} +2 -2
  20. package/dist/dist-UXDXDLES.js +1 -0
  21. package/dist/dist-es-B5M7V6O6.js +1 -0
  22. package/dist/{dist-es-DQDVBBVA.js → dist-es-FU66ZQS5.js} +1 -1
  23. package/dist/dist-es-KE65J6GC.js +1 -0
  24. package/dist/dist-es-PFLN3FTL.js +5 -0
  25. package/dist/dist-es-U3NYQORW.js +1 -0
  26. package/dist/dist-es-VG3XXJ7M.js +2 -0
  27. package/dist/dist-es-WAHVDQ3F.js +2 -0
  28. package/dist/event-streams-SGW54BDO.js +1 -0
  29. package/dist/index.js +180 -180
  30. package/dist/loadSso-WRXP2HXL.js +1 -0
  31. package/dist/signin-JB7STGTR.js +1 -0
  32. package/dist/sso-oidc-LTNOJMPI.js +1 -0
  33. package/dist/sts-RKUL4Q47.js +5 -0
  34. package/package.json +15 -15
  35. package/templates/LICENSE-SCAFFOLD.md +63 -0
  36. package/templates/docs/fumadocs/app/global.css +2 -2
  37. package/templates/workflows/inngest/welcome-email.ts +18 -2
  38. package/dist/aws-kms-W5N62I3Q.js +0 -1
  39. package/dist/chunk-224RJRPV.js +0 -5
  40. package/dist/chunk-2YUF6TO6.js +0 -2
  41. package/dist/chunk-44JV4JDH.js +0 -1
  42. package/dist/chunk-5LSLUC7O.js +0 -9
  43. package/dist/chunk-AAIUIEEA.js +0 -1
  44. package/dist/chunk-CHWVD37K.js +0 -1
  45. package/dist/chunk-DATQDZ23.js +0 -1
  46. package/dist/chunk-IY2KKEUD.js +0 -1
  47. package/dist/chunk-M2Z4KZL3.js +0 -20
  48. package/dist/chunk-U4BHGI6P.js +0 -1
  49. package/dist/chunk-WI7DO2VU.js +0 -1
  50. package/dist/chunk-YHGYZK4L.js +0 -1
  51. package/dist/dist-27O4E2DL.js +0 -1
  52. package/dist/dist-es-2W7PQEXN.js +0 -5
  53. package/dist/dist-es-CAS2CDUC.js +0 -2
  54. package/dist/dist-es-GO22VTF3.js +0 -1
  55. package/dist/dist-es-KKEGJGC4.js +0 -2
  56. package/dist/dist-es-LARTXLYL.js +0 -1
  57. package/dist/dist-es-O2XJNCOH.js +0 -1
  58. package/dist/loadSso-LSHML5XP.js +0 -1
  59. package/dist/signin-3DEIU5DH.js +0 -1
  60. package/dist/sso-oidc-5FB6AI4I.js +0 -1
  61. package/dist/sts-7GUSARTO.js +0 -6
  62. package/templates/LICENSE-INDEPENDENT.md +0 -93
  63. /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-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"})+`
2
+ import"./chunk-IYWUY3VA.js";import{execSync as Kc}from"child_process";import Ks from"fs";import $s from"path";import*as ot from"@clack/prompts";import F from"picocolors";import{Command as Ws}from"commander";import In from"fs";import Vt from"path";import{fileURLToPath as Gs}from"url";function Hs(){try{let t=Vt.dirname(Gs(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=Hs();var Xs="create-sailor";function Cn(){let e=new Ws;return e.name(Xs).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 rt(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 Zc=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),s=rt(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 zs=new Set(["gateway","direct","custom","none"]);function zt(e){if(!e)return!1;let t=e.trim().toLowerCase();return zs.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 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(`
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 ar 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.sensenova.cn/docs",baseURL:"https://token.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 Js=["openai","anthropic","google"],Qs=["openai"];function on(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let n=t.length>0?t:[...Js];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:[...Qs];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"}],Zs=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(s=>s.trim().toLowerCase()).filter(Boolean);if(t.includes("none"))return[];let n=[],o=new Set;for(let s of t)Zs.has(s)&&!o.has(s)&&(n.push(s),o.add(s));return n}import ee from"fs";import T from"path";import{fileURLToPath as er}from"url";var tr=er(import.meta.url),Dn=T.dirname(tr),nr={web:"vercel",landing:"vercel","design-docs":"vercel","sailor-docs":"vercel",gateway:"cloudflare-workers","python-ai":"ecs-docker"};function or(){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:"cloudflare-pages","design-docs":"cloudflare-pages","sailor-docs":"cloudflare-pages",gateway:"cloudflare-workers","python-ai":"ecs-docker"};case"selfhost":return{web:"standalone",landing:"standalone","design-docs":"standalone","sailor-docs":"standalone",gateway:"ecs-docker","python-ai":"ecs-docker"};case"railway":return{web:"railway",landing:"railway","design-docs":"railway","sailor-docs":"railway",gateway:"railway","python-ai":"railway"};case"none":case"vercel":return{...nr}}}function sr(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])=>`${sr(i)}="${a}"`)].join(`
6
+ `);await ee.promises.appendFile(n,`${r}
7
+ `)}async function Vn(e,t){if(t==="none")return;let n=or();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 rr={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 ir(e){return e?rr[e]??"stable":"stable"}function Xe(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function Ee(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 s=ir(o);s!=="stable"&&t.push({flag:n,provider:o,status:s})}return t}function ve(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:ve(e.cronJobs,!0),auditLog:ve(e.auditLog,!1),apiKeys:ve(e.apiKeys,!0),webhooks:ve(e.webhooks,!0),commandPalette:ve(e.commandPalette,!0),cookieConsent:ve(e.cookieConsent,!0),legalPages:ve(e.legalPages,!0),chinaCompliance:ve(e.chinaCompliance,n)}}async function cr(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(ar.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,p=!!e.analytics,u=!!e.sms,d=e.i18n!==void 0,h=!!e.yes||!process.stdin.isTTY,f,E,S,m,P,G,M,fe=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=s?e.payment:tn(f);P=Ht(W),G=Wt(W),M=Xt(e.auth);let He="gateway";if(r){let $=e.ai?.trim().toLowerCase()??"";zt($)?He=$:He="direct"}let st=on({mode:He,providerIds:r?Jt(e.ai):void 0});pe=st.mode,Z=st.routing,j=st.providerIds,C=Zt(e.deploy),H=Qt(e.docs,t),le=d?!!e.i18n:!0}else{let W=await cr(e,n,o,r);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=s?e.payment:tn(f);P=Ht(He),G=Wt(He),M=Xt(o?e.auth:W.auth);let st=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:st});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),ye=i?e.email:w.email,qe=On(a?e.storage:void 0,w.storage),Ge=c?e.monitoring:w.monitoring,Se=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),he=$n({cronJobs:e.cronJobs,auditLog:e.auditLog,apiKeys:e.apiKeys,commandPalette:e.commandPalette,cookieConsent:e.cookieConsent,legalPages:e.legalPages,chinaCompliance:e.chinaCompliance},f),Ys=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}]),qs={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:ye,storage:qe,monitoring:Ge,analytics:Se,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:he.cronJobs,auditLog:he.auditLog,apiKeys:he.apiKeys,commandPalette:he.commandPalette,cookieConsent:he.cookieConsent,legalPages:he.legalPages,chinaCompliance:he.chinaCompliance};return{region:f,orm:E,database:S,databaseHost:m,payment:P,paymentChoice:G,auth:M,socialLoginIds:fe,aiMode:pe,aiRouting:Z,aiProviders:j,customAiEndpoint:K,deployTarget:C,deployTargets:wn,docs:H,i18n:le,email:ye,storage:qe,monitoring:Ge,analytics:Se,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:he,previewSelections:Ys,config:qs}}import{execFileSync as Ot}from"child_process";import Lt from"fs";import $e from"path";import gt from"picocolors";import Tc from"update-notifier";import A from"picocolors";function pr(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function qn(e){let t=pr(),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=Xe(h.status),E=` ${o} ${h.flag} (${h.provider}) ${f}`;a.push(t?A.yellow(E):E)}a.push("",` ${t?A.dim(Ee("foundation")):Ee("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:"}`,` ${s} Star us https://github.com/nebutra/nebutra-sailor`,` ${r} Free license https://nebutra.com/get-license`,""),process.stdout.write(a.join(`
9
9
  `)+`
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";
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:""}],xp=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 lr(e){ze.mkdirSync(e,{recursive:!0})}function te(e,t){lr(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 dr(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 ds(){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 ur(){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 us(e){te(B.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
99
+ `}function mr(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 ms(){return`# Plausible \u2014 privacy-friendly analytics
119
+ `)}function gr(){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 gs(e){te(B.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
122
+ `}function fr(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 fs(){return`# Umami \u2014 self-hostable analytics
142
+ `)}function yr(){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 ys(e){let t=`"use client";
145
+ `}function Sr(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 Ss(){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 hr(){return`# Mixpanel \u2014 product analytics
185
185
  MIXPANEL_TOKEN=
186
186
  NEXT_PUBLIC_MIXPANEL_TOKEN=
187
- `}function hs(e){te(B.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
187
+ `}function Er(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 Es(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
213
+ `)}function vr(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
214
214
  NEXT_PUBLIC_BAIDU_STATS_ID=
215
- `}function vs(e){te(B.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
215
+ `}function br(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 bs(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
243
+ `)}function _r(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
244
244
  NEXT_PUBLIC_SENSORS_SERVER_URL=
245
245
  NEXT_PUBLIC_SENSORS_APP_JS_URL=
246
- `}function _s(e){te(B.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
246
+ `}function Pr(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 Ps(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
271
+ `)}function wr(){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 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-NJH3URWV.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,`
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(!ze.existsSync(s))return;let r=o.id;try{switch(r){case"posthog":dr(s),Ie(e,ur());return;case"plausible":mr(s),Ie(e,gr());return;case"umami":fr(s),Ie(e,yr());return;case"mixpanel":Sr(s),Ie(e,hr());return;case"baidu":Er(s),Ie(e,vr());return;case"sensors":br(s),Ie(e,_r());return;case"growingio":Pr(s),Ie(e,wr());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.`)}}import{getBrandOrigin as Ar}from"@nebutra/brand/metadata-helpers";var Ir=Ar("analytics");function Cr(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function Xn(e,t={}){Cr(t)||(async()=>{try{let n=await import("./dist-SFI2IGZ2.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??Ir},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 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 xr(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),xr(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"),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
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")),ht(s,"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")),ht(r,"better-auth"),St(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(s,"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")),ht(r,"nextauth"),St(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(s,"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")),ht(r,"supabase"),St(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(s,"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 xe from"fs";import Ce from"path";function Cs(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 Rr(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(
@@ -415,15 +415,15 @@ export async function GET(req: NextRequest) {
415
415
 
416
416
  ${o[e.id]}
417
417
 
418
- // TODO: fetch user profile from ${e.name} using the access token.
419
- // TODO: upsert the user into your primary auth provider (${t}).
420
- // e.g. clerk.users.createUser(...) or betterAuth.signIn.oauth(...).
421
- // Persist a session cookie before redirecting.
418
+ // SAMPLE (intentional): fetch user profile from ${e.name} with the
419
+ // access token, then upsert into primary auth (${t}) \u2014
420
+ // e.g. clerk.users.createUser(...) or betterAuth.signIn.oauth(...).
421
+ // Persist a session cookie before redirecting.
422
422
 
423
423
  void state;
424
424
  return NextResponse.redirect(new URL("/dashboard", req.url));
425
425
  }
426
- `}function xs(e){return`"use client";
426
+ `}function kr(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){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(`
469
+ `}function Jn(e){xe.mkdirSync(e,{recursive:!0})}function Tr(e,t){let n=Ce.join(e,".env.example");xe.existsSync(n)?xe.appendFileSync(n,`
470
+ `+t):xe.writeFileSync(n,t)}function Nr(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=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(`
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 s=new Set,r=[];for(let p of t){if(s.has(p))continue;s.add(p);let u=Un(p);u&&r.push(u)}if(r.length===0)return;for(let p of r)Tr(e,Nr(p));let i=Ce.join(o,"src","app","api","auth","callback");for(let p of r){let u=Ce.join(i,p.id);Jn(u);let d=Ce.join(u,"route.ts");xe.writeFileSync(d,Rr(p,n))}let a=Ce.join(o,"src","components","auth");Jn(a);let c=Ce.join(a,"SocialLoginButtons.tsx");xe.writeFileSync(c,kr(r))}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 $p=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 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=vt.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(`
475
475
  `)?"":`
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(`
476
+ `;ne.appendFileSync(o,`${a}${r}
477
+ `)}var Or=["design","iam","commerce","integrations","platform","ops","ai"];function Re(e,t){for(let o of Or){let s=vt.join(e,"packages",o,t);if(ne.existsSync(s))return s}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 Lr(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
+ `);Je.appendFileSync(n,r)}function Ur(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)?Je.writeFileSync(o,s.replace(r,`${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 s=Zn(t);if(!s)throw new Error(`Unknown cache provider "${t}". Valid ids: ${Et.map(r=>r.id).join(", ")}`);o&&(Lr(e,s),Ur(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 Zp=bt.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: ${bt.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 Pt from"fs";import Mr 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 ro(e){return _t.find(t=>t.id===e)}var sl=_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=ro(t);if(!o)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${_t.map(r=>r.id).join(", ")}`);let s=Mr.join(e,"apps","studio");if(o.id==="none"){z(e,"sanity"),Pt.existsSync(s)&&Pt.rmSync(s,{recursive:!0,force:!0});return}o.id!=="sanity"&&(z(e,"sanity"),Pt.existsSync(s)&&Pt.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 Dr=O.join("apps","web"),sn=O.join("src","components","compliance"),at=O.join("src","app","[locale]");function re(e){return O.join(e,Dr)}function Fr(e){U.mkdirSync(e,{recursive:!0})}function J(e,t){Fr(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(`
480
480
  `)[0]??""))return;U.appendFileSync(n,`
481
481
  `+t+`
482
482
  `)}else U.writeFileSync(n,t+`
483
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`,Ds=`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`,jr=`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
- `,Fs=`export function IcpFooter() {
536
+ `,Br=`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
- `,js=`export function PublicSecurityFooter() {
550
+ `,Vr=`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
- `,Bs=`"use client";
567
+ `,Kr=`"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
- `,Vs=`interface AigcDisclaimerProps {
721
+ `,$r=`interface AigcDisclaimerProps {
722
722
  className?: string;
723
723
  }
724
724
 
@@ -738,7 +738,7 @@ export function AigcDisclaimer({ className }: AigcDisclaimerProps) {
738
738
  </div>
739
739
  );
740
740
  }
741
- `,Ks=`---
741
+ `,Yr=`---
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
@@ -883,7 +883,7 @@ 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
- `,$s=`---
886
+ `,qr=`---
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
@@ -1002,7 +1002,7 @@ 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
- `,Ys=`---
1005
+ `,Gr=`---
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
@@ -1026,8 +1026,8 @@ Administration of China.
1026
1026
 
1027
1027
  | Model / \u6A21\u578B | Provider / \u63D0\u4F9B\u65B9 | Use Case / \u7528\u9014 |
1028
1028
  | --- | --- | --- |
1029
- | _e.g. GPT-4o_ | _OpenAI_ | _Chat, content drafting_ |
1030
- | _e.g. Claude 3.5 Sonnet_ | _Anthropic_ | _Reasoning, code generation_ |
1029
+ | _e.g. GPT-5.5_ | _OpenAI_ | _Chat, content drafting_ |
1030
+ | _e.g. Claude Sonnet 4.6_ | _Anthropic_ | _Reasoning, code generation_ |
1031
1031
  | _e.g. \u901A\u4E49\u5343\u95EE_ | _\u963F\u91CC\u4E91_ | _\u4E2D\u6587\u5185\u5BB9\u751F\u6210_ |
1032
1032
 
1033
1033
  ---
@@ -1084,7 +1084,7 @@ 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
- `,qs=`---
1087
+ `,Hr=`---
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
@@ -1149,7 +1149,7 @@ 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
- `,Gs=`---
1152
+ `,Wr=`---
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
@@ -1191,26 +1191,26 @@ 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 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}
1194
+ `;async function Xr(e,t){let n=re(e);if(!U.existsSync(n))return;let o=O.join(n,"src","components","compliance","Footer.tsx");J(o,jr);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 zr(e,t){let n=re(e);if(!U.existsSync(n))return;let o=O.join(n,"src","components","compliance","CookieBanner.tsx");J(o,Kr)}async function Jr(e,t){let n=re(e);if(!U.existsSync(n))return;let o=O.join(n,at,"privacy","page.mdx");J(o,Yr)}async function Qr(e,t){let n=re(e);if(!U.existsSync(n))return;let o=O.join(n,at,"terms","page.mdx");J(o,qr)}async function Zr(e){let t=re(e);if(!U.existsSync(t))return;let n=O.join(t,sn,"IcpFooter.tsx");J(n,Br),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 ei(e){let t=re(e);if(!U.existsSync(t))return;let n=O.join(t,sn,"PublicSecurityFooter.tsx");J(n,Vr),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 ti(e){let t=re(e);if(!U.existsSync(t))return;let n=O.join(t,sn,"AigcDisclaimer.tsx");J(n,$r),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 ni(e){let t=re(e);if(!U.existsSync(t))return;let n=O.join(t,at,"aigc-disclosure","page.mdx");J(n,Gr)}async function oi(e){let t=re(e);if(!U.existsSync(t))return;let n=O.join(t,at,"cross-border-data","page.mdx");J(n,Hr)}async function si(e){let t=re(e);if(!U.existsSync(t))return;let n=O.join(t,at,"pii-collection","page.mdx");J(n,Wr)}async function ao(e,t){try{await Xr(e,t),await zr(e,t),await Jr(e,t),await Qr(e,t),(t==="cn"||t==="hybrid")&&(await Zr(e),await ei(e),await ti(e),await ni(e),await oi(e),await si(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 ri from"fs";import ii from"path";async function co(e,t){let n=ii.join(e,"nebutra.config.json");ri.writeFileSync(n,JSON.stringify(t,null,2)+`
1199
+ `)}import R from"fs";import ke from"path";function ai(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 ci(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 pi(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"){ai(o);return}let s=ke.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",pi(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=ci(a),a=lo(a)),a!==i&&R.writeFileSync(s,a)}function li(e){let t=ke.join(e,".env.example");return R.existsSync(t)?R.readFileSync(t,"utf8"):""}function di(e,t,n,o){let s=ke.join(e,".env.example"),r=li(e),i=o?`# ${o}
1203
1203
  ${t}="${n}"
1204
1204
  `:`${t}="${n}"
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(`
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 ui(e,t){let n=ke.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(p=>!o.includes(p.trim()));if(i.length===0)return;let a=i.map(p=>` ${p}`).join(`
1207
+ `),c=o.replace(s,`$1
1208
+ ${a}$2`);R.writeFileSync(n,c)}function mi(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 s=o.placeholder.replace(/\$PROJECT/g,n);di(e,o.name,s,o.comment)}t.prismaDatasourceExtras&&t.prismaDatasourceExtras.length>0&&ui(e,t.prismaDatasourceExtras),t.keepDirectUrl&&mi(e)}}import be from"fs";import Te from"path";import{fileURLToPath as gi}from"url";var fi=gi(import.meta.url),go=Te.dirname(fi),yi=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,fo=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function Si(e){let t=[Te.join(go,"..","templates","docs",e),Te.join(go,"..","..","templates","docs",e)];for(let n of t)if(be.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=Si(t.framework),o=Te.join(e,"apps","docs");if(!be.existsSync(n))throw new Error(`Docs template not found: ${n}`);So(n,o),ho(o,{"{PRODUCT_NAME}":t.projectName})}function So(e,t){be.mkdirSync(t,{recursive:!0});for(let n of be.readdirSync(e,{withFileTypes:!0})){let o=Te.join(e,n.name),s=Te.join(t,n.name);n.isDirectory()?So(o,s):be.copyFileSync(o,s)}}function ho(e,t){for(let n of be.readdirSync(e,{withFileTypes:!0})){let o=Te.join(e,n.name);if(n.isDirectory())ho(o,t);else if(yi.test(n.name)){let s=be.readFileSync(o,"utf-8");for(let[r,i]of Object.entries(t))s=s.split(r).join(i);be.writeFileSync(o,s)}}}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 Al=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 hi(e,t){let n=Ne.join(e,".env.example");Oe.existsSync(n)?Oe.appendFileSync(n,`
1210
+ `+t):Oe.writeFileSync(n,t)}function Ei(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
- `}var hi=`/**
1213
+ `}var vi=`/**
1214
1214
  * Public inputs accepted by the \`sendEmail\` wrapper.
1215
1215
  * Keep the surface minimal \u2014 individual providers may accept more, but
1216
1216
  * consumers should code against this shape for portability.
@@ -1230,7 +1230,7 @@ export interface SendEmailResult {
1230
1230
  /** Raw provider response \u2014 useful for debugging, not a stable contract. */
1231
1231
  raw?: unknown;
1232
1232
  }
1233
- `;function Ei(){return`/**
1233
+ `;function bi(){return`/**
1234
1234
  * @${Le.slice(1)} \u2014 Resend transactional email wrapper.
1235
1235
  *
1236
1236
  * Docs: https://resend.com/docs
@@ -1269,7 +1269,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1269
1269
  }
1270
1270
 
1271
1271
  export type { SendEmailInput, SendEmailResult } from "./types";
1272
- `}function vi(){return`/**
1272
+ `}function _i(){return`/**
1273
1273
  * @${Le.slice(1)} \u2014 Postmark transactional email wrapper.
1274
1274
  *
1275
1275
  * Docs: https://postmarkapp.com/developer
@@ -1307,7 +1307,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1307
1307
  }
1308
1308
 
1309
1309
  export type { SendEmailInput, SendEmailResult } from "./types";
1310
- `}function bi(){return`/**
1310
+ `}function Pi(){return`/**
1311
1311
  * @${Le.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1312
1312
  *
1313
1313
  * Docs: https://docs.aws.amazon.com/ses
@@ -1363,7 +1363,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1363
1363
  }
1364
1364
 
1365
1365
  export type { SendEmailInput, SendEmailResult } from "./types";
1366
- `}function _i(){return`/**
1366
+ `}function wi(){return`/**
1367
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
@@ -1413,7 +1413,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1413
1413
  }
1414
1414
 
1415
1415
  export type { SendEmailInput, SendEmailResult } from "./types";
1416
- `}function Pi(){return`/**
1416
+ `}function Ai(){return`/**
1417
1417
  * @${Le.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1418
1418
  *
1419
1419
  * Docs: https://cloud.tencent.com/document/product/1288
@@ -1461,7 +1461,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1461
1461
  }
1462
1462
 
1463
1463
  export type { SendEmailInput, SendEmailResult } from "./types";
1464
- `}function wi(){return`/**
1464
+ `}function Ii(){return`/**
1465
1465
  * @${Le.slice(1)} \u2014 \u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1 via SMTP (nodemailer).
1466
1466
  *
1467
1467
  * Docs: https://qiye.163.com/help
@@ -1499,32 +1499,32 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1499
1499
  }
1500
1500
 
1501
1501
  export type { SendEmailInput, SendEmailResult } from "./types";
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: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(`
1502
+ `}function Ci(e){switch(e){case"resend":return bi();case"postmark":return _i();case"ses":return Pi();case"aliyun-dm":return wi();case"tencent-ses":return Ai();case"netease":return Ii();case"none":return`export {};
1503
+ `}}function xi(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 s=Ne.join(e,"packages","email"),r=Ne.join(s,"src");Oe.existsSync(r)&&Oe.rmSync(r,{recursive:!0,force:!0}),an(Ne.join(s,"package.json"),xi(o)),an(Ne.join(r,"types.ts"),vi),an(Ne.join(r,"index.ts"),Ci(o.id)),hi(e,Ei(o))}import de from"fs";import bo from"path";function Ri(e,t){return new RegExp(`^\\s*${t}\\s*=`,"m").test(e)}function _o(e){return e.endsWith(`
1505
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
1506
+ `}async function Po(e,t){let n=bo.join(e,".env"),o=bo.join(e,".env.local"),s=de.existsSync(n)?de.readFileSync(n,"utf8"):"",r=de.existsSync(o)?de.readFileSync(o,"utf8"):"",i=`${s}
1507
+ ${r}`,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=>!Ri(i,p.name)).map(p=>`${p.name}="${p.value}"`);if(a.length===0)return;let c=`# Automatically injected by create-sailor
1508
1508
  ${a.join(`
1509
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"}
1510
+ `;try{let p=de.readFileSync(o,"utf8"),u=_o(p);de.writeFileSync(o,`${u}
1511
+ ${c}`)}catch{try{de.writeFileSync(o,c,{flag:"wx"})}catch{let p=de.readFileSync(o,"utf8");de.writeFileSync(o,`${_o(p)}
1512
+ ${c}`)}}}import Ao from"crypto";import pt from"fs";import wo from"path";function Ue(e){return Ao.randomBytes(e).toString("base64").replace(/=+$/,"")}function ki(e){return Ao.randomBytes(e).toString("hex")}function Ti(){return{AUTH_SECRET:Ue(32),NEXTAUTH_SECRET:Ue(32),BETTER_AUTH_SECRET:Ue(32),JWT_SECRET:Ue(32),WEBHOOK_SECRET:ki(16),ENCRYPTION_KEY:Ue(32),API_SECRET_KEY:Ue(32),SESSION_SECRET:Ue(32)}}function Ni(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Oi(e,t,n){let o=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),s=Ni(n);return e.replace(o,`${t}="${s}"`)}async function Io(e){let t=wo.join(e,".env.example"),n=wo.join(e,".env.local");if(!pt.existsSync(t))return null;try{let o=pt.readFileSync(t,"utf8"),s=Ti(),i=pt.existsSync(n)?pt.readFileSync(n,"utf8"):o;for(let a of Object.keys(s))i=Oi(i,a,s[a]);return pt.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 Co(e){return At.find(t=>t.id===e)}var Fl=At.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function xo(e,t,n="global"){let o=Co(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 No}from"child_process";import L from"fs";import Li from"os";import ie from"path";import Ui from"ignore";var Mi={mirror:{repo:process.env.SAILOR_TEMPLATE_REPO||"Nebutra/Sailor-Template",ref:process.env.SAILOR_TEMPLATE_REF||"main",applyIgnore:!1,allowMutableFallback:process.env.SAILOR_TEMPLATE_ALLOW_MUTABLE_FALLBACK==="1"},main:{repo:"Nebutra/Nebutra-Sailor",ref:"main",applyIgnore:!0,allowMutableFallback:process.env.SAILOR_TEMPLATE_ALLOW_MUTABLE_FALLBACK==="1"}};function Di(){let e=process.env.SAILOR_TEMPLATE_LOCAL_DIR;if(!(!e||e.trim().length===0))return ie.resolve(e.trim())}var Fi=new Set(["node_modules",".git","dist",".next",".turbo"]);function ji(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!Fi.has(s)}})}function Bi(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function Vi(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function Oo(e){return/^[0-9a-f]{7,40}$/i.test(e)}function Ki(e,t){let n=`https://github.com/${e}.git`,o=[`refs/heads/${t}`,`refs/tags/${t}`];for(let s of o)try{let r=No("git",["ls-remote",n,s],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!r)continue;let[i]=r.split(/\s+/);if(Oo(i))return i}catch{}return null}async function $i(e,t){if(Oo(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=Ki(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 Lo(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+"/"),Lo(e,r,n)):n.push(i)}}function Ro(e){let t=ie.join(e,".templateignore");if(!L.existsSync(t))return;let n=L.readFileSync(t,"utf8"),o=Ui().add(n),s=[];Lo(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,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 ko(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 To(e,t){No("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 Yi(e,t){let n=L.mkdtempSync(ie.join(Li.tmpdir(),"create-sailor-")),o=ie.join(n,"template.tar.gz");try{let s=await $i(e.repo,e.ref);await ko(Vi(e.repo,s),o),To(o,t)}catch(s){if(!e.allowMutableFallback)throw s;cn(t),await ko(Bi(e.repo,e.ref),o),To(o,t)}finally{L.rmSync(n,{recursive:!0,force:!0})}}async function Uo(e){L.mkdirSync(e,{recursive:!0});let t=Di();if(t){if(!L.existsSync(t))throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR does not exist: ${t}`);cn(e),ji(t,e);try{Ro(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=Mi[r];try{if(await Yi(i,e),i.applyIgnore)try{Ro(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"}
1512
1513
 
1513
1514
  Ensure you have internet access and 'tar' installed.
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)}
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
1518
- > [Nebutra-Sailor Independent Developer License](./LICENSE). Free for
1519
- > individuals/OPC with \u2264 1 FTE and < $1M ARR; upgrade for larger teams at
1520
- > https://nebutra.com/get-license. The upstream repository remains
1521
- > AGPL-3.0 \u2014 see \`LICENSE-AGPL-REFERENCE.md\`.
1522
-
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";
1515
+ You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import It from"fs";import pn from"path";var qi="node scripts/governance/lint-no-raw-inputs.mjs",Gi="node scripts/governance/lint-repository-seam.mjs",Hi="node scripts/governance/lint-brand-literals.mjs",Wi="node scripts/governance/lint-microcopy.mjs",Xi=/\bnode\s+scripts\/(governance\/)?lint-[\w-]+\.mjs/g,zi=/\bnode\s+scripts\/lint-[\w-]+\.mjs/,Ji={scanRoots:["apps"],primitivesImport:"@nebutra/ui/primitives",whitelist:["/storybook/src/stories/","/design-docs/src/components/previews/","/sailor-docs/src/components/previews/","\\.test\\.tsx?$","/__tests__/"]},Qi={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:[]},Mo={governedPaths:["apps","packages/commerce","packages/integrations/email"],allowExpressions:["Nebutra","\u4E91\u6BD3\u667A\u80FD","\u4E91\u6BD3","^https?://([a-z0-9-]+\\.)?nebutra\\.com(?:/|$)","^https?://([a-z0-9-]+\\.)?nebutra\\.ai(?:/|$)","#0033FE","#0BF1C3"],knownExemptPatterns:["\\.stories\\.tsx?$","/__tests__/","\\.test\\.tsx?$","/previews/","^packages/design/brand/","^packages/design/tokens/","^packages/design/design-tokens/"],allowlist:[]},ea=["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/src/app/[lang]/layout.tsx","apps/landing/src/app/api/blog/comments/route.ts","apps/landing/src/app/api/blog/reactions/route.ts","apps/landing/src/app/api/og/route.ts","apps/landing/src/app/apple-icon.tsx","apps/landing/src/components/auth/google-one-tap.tsx","apps/landing/src/components/cookie-consent-banner.tsx","apps/landing/src/components/marketing/ProductHuntSection.tsx","apps/landing/src/components/marketing/TestimonialsSection.tsx","apps/landing/src/i18n/request.ts","apps/landing/src/lib/analytics/emit.ts","apps/landing/src/lib/blog-fallback.ts","apps/landing/src/lib/constants/playbook-data.ts","apps/landing/src/lib/constants/resources-data.ts","apps/landing/src/lib/constants/solutions-data.ts","apps/landing/src/lib/docs-links.ts","apps/landing/src/lib/env.ts","apps/landing/src/lib/landing-content.ts","apps/landing/src/lib/seo/metadata.ts","apps/landing/src/lib/seo/site-routes.ts","apps/landing/src/lib/status-checks.ts","apps/landing/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 ta(e,t){let n=(e??"").replace(Xi,"").split("&&").map(s=>s.trim()).filter(Boolean).join(" && ");return[n.length>0?n:"biome check .",...t].join(" && ")}function na(e){let t=new RegExp(Mo.allowExpressions.join("|"));return ea.filter(n=>{try{return t.test(It.readFileSync(pn.join(e,n),"utf8"))}catch{return!1}})}async function Do(e,t){let n=t.database!=="none",o=[qi];n&&o.push(Gi),o.push(Hi),o.push(Wi);let s={...Mo,allowlist:na(e)},r={rawInputs:Ji,brandLiterals:s,microcopyRules:Zi};n&&(r.repositorySeam=Qi);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(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"&&zi.test(d)&&delete p.scripts[u];p.scripts.lint=ta(p.scripts.lint,o),It.writeFileSync(a,JSON.stringify(p,null,2)+`
1517
+ `)}return{lints:o,configWritten:!0}}import{createHmac as sa,randomBytes as ra}from"crypto";import Q from"fs";import ae from"path";import{fileURLToPath as ia}from"url";var oa=[{id:"v1",key:"nebutra-sailor:scaffold-marker:v1"}];function Fo(){let e=oa[0];if(!e)throw new Error("license-signing-keys: registry is empty \u2014 at least one key is required.");return e}var aa=ia(import.meta.url),jo=ae.dirname(aa),Bo="scaffold-meta.json",Vo=".nebutra";function ca(e){if(e)return e;let t=[ae.join(jo,"..","templates"),ae.join(jo,"..","..","templates")];for(let n of t)if(Q.existsSync(n))return n;return t[0]}function pa(e,t){let n=`${e.cliVersion}|${e.scaffoldedAt}|${e.projectName}|${e.nonce}`;return sa("sha256",t).update(n).digest("hex")}function Ko(e,t){let n=[],o=ca(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)||/Functional Source License/i.test(h))&&(Q.renameSync(s,ae.join(e,"LICENSE-UPSTREAM-REFERENCE.md")),n.push("LICENSE-UPSTREAM-REFERENCE.md (preserved upstream licence)"))}let r=ae.join(o,"LICENSE-SCAFFOLD.md");if(!Q.existsSync(r))throw new Error(`LICENSE-SCAFFOLD.md template missing at ${r}; cannot emit license.`);Q.copyFileSync(r,ae.join(e,"LICENSE")),n.push("LICENSE");let i=new Date().toISOString(),a=ra(12).toString("hex"),c=Fo(),p=pa({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. Provenance only \u2014 the MIT licence in LICENSE applies unconditionally and does not depend on this file or its signature.",license:{tier:"mit-scaffold",file:"LICENSE",upgradeUrl:"https://nebutra.com/get-license"}},d=ae.join(e,Vo);Q.mkdirSync(d,{recursive:!0}),Q.writeFileSync(ae.join(d,Bo),`${JSON.stringify(u,null,2)}
1518
+ `),n.push(`${Vo}/${Bo}`);let _=ae.join(e,"README.md");if(Q.existsSync(_)){let h=Q.readFileSync(_,"utf-8");h.includes("Scaffolded by `create-sailor`")||(Q.writeFileSync(_,`> **License notice:** Scaffolded by \`create-sailor\`. The Nebutra-Sailor
1519
+ > code in this project is [MIT licensed](./LICENSE) \u2014 commercial use, closed
1520
+ > source, no fee, no attribution required. The upstream monorepo is
1521
+ > FSL-1.1-ALv2 \u2014 see \`LICENSE-UPSTREAM-REFERENCE.md\`.
1522
+
1523
+ `+h),n.push("README.md (prepended license notice)"))}return{wrote:n}}import Me from"fs";import ln from"path";async function $o(e,t){let n=ln.join(e,"packages","mcp");if(t==="off"){Me.existsSync(n)&&Me.rmSync(n,{recursive:!0,force:!0});let s=ln.join(e,"packages","cli","src","commands","mcp-server.ts");Me.existsSync(s)&&Me.rmSync(s,{force:!0});return}let o=ln.join(e,".env.example");if(Me.existsSync(o)){let s=Me.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(`
1524
+ `);Me.appendFileSync(o,i)}}}import lt from"fs";import Yo from"path";async function qo(e,t,n){let o=Yo.join(e,"packages","metering"),s;if(t==="auto"?s=n!=="none"?"on":"off":t==="on"||t==="off"?s=t:s="off",s==="off"){lt.existsSync(o)&&lt.rmSync(o,{recursive:!0,force:!0});return}let r=Yo.join(e,".env.example");if(!lt.existsSync(r))return;let i=lt.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(`
1525
+ `);lt.appendFileSync(r,c)}}import ue from"fs";import D from"path";var Go=[{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:""}],ud=Go.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ho(e){return Go.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 la(e){ue.mkdirSync(e,{recursive:!0})}function un(e,t){let n=D.join(e,"package.json");if(!ue.existsSync(n))return;let o;try{o=JSON.parse(ue.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};ue.writeFileSync(n,JSON.stringify(i,null,2)+`
1526
+ `)}function ce(e,t){la(D.dirname(e)),ue.writeFileSync(e,t)}function dt(e,t){let n=D.join(e,".env.example");ue.existsSync(n)?ue.appendFileSync(n,`
1527
+ `+t):ue.writeFileSync(n,t)}function da(e){let t=`import * as Sentry from "@sentry/nextjs";
1528
1528
 
1529
1529
  Sentry.init({
1530
1530
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
@@ -1553,7 +1553,7 @@ Sentry.init({
1553
1553
  tracesSampleRate: 1.0,
1554
1554
  environment: process.env.NODE_ENV,
1555
1555
  });
1556
- `,r=`/**
1556
+ `,s=`/**
1557
1557
  * Next.js instrumentation hook \u2014 wires Sentry into Node and Edge runtimes.
1558
1558
  * See https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation
1559
1559
  */
@@ -1567,14 +1567,14 @@ export async function register() {
1567
1567
  }
1568
1568
 
1569
1569
  export { captureRequestError as onRequestError } from "@sentry/nextjs";
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
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"),s)}function ua(){return`# Sentry \u2014 error tracking + performance monitoring
1571
1571
  # Get your DSN from https://sentry.io/settings/projects/<project>/keys/
1572
1572
  SENTRY_DSN=
1573
1573
  NEXT_PUBLIC_SENTRY_DSN=
1574
1574
  SENTRY_ORG=
1575
1575
  SENTRY_PROJECT=
1576
1576
  SENTRY_AUTH_TOKEN=
1577
- `}function ua(e){let t=`/**
1577
+ `}function ma(e){let t=`/**
1578
1578
  * Next.js instrumentation hook \u2014 wires Datadog APM (dd-trace) into Node runtime.
1579
1579
  * Edge runtime is not supported by dd-trace; only nodejs is initialized.
1580
1580
  */
@@ -1622,7 +1622,7 @@ export function initDatadogRum(): void {
1622
1622
  });
1623
1623
  initialized = true;
1624
1624
  }
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
1625
+ `;ce(D.join(e,"instrumentation.ts"),t),ce(D.join(e,"src","lib","monitoring","datadog-rum.ts"),n)}function ga(){return`# Datadog \u2014 APM + RUM
1626
1626
  # Server APM (dd-trace)
1627
1627
  DD_API_KEY=
1628
1628
  DD_APP_KEY=
@@ -1637,7 +1637,7 @@ NEXT_PUBLIC_DD_SITE=datadoghq.com
1637
1637
  NEXT_PUBLIC_DD_SERVICE=sailor-web
1638
1638
  NEXT_PUBLIC_DD_ENV=production
1639
1639
  NEXT_PUBLIC_DD_VERSION=
1640
- `}function ga(e){let t=`/**
1640
+ `}function fa(e){let t=`/**
1641
1641
  * Bugsnag server-side initialization.
1642
1642
  * Import this once at the top of your server entrypoint or a shared init module.
1643
1643
  */
@@ -1686,11 +1686,11 @@ export function getBugsnagErrorBoundary() {
1686
1686
  errorBoundary = plugin.createErrorBoundary(React) as typeof errorBoundary;
1687
1687
  return errorBoundary;
1688
1688
  }
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
1689
+ `;ce(D.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),ce(D.join(e,"src","lib","monitoring","bugsnag.client.tsx"),n)}function ya(){return`# Bugsnag \u2014 error tracking
1690
1690
  BUGSNAG_API_KEY=
1691
1691
  NEXT_PUBLIC_BUGSNAG_API_KEY=
1692
1692
  APP_VERSION=
1693
- `}function ya(e){ce(D.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1693
+ `}function Sa(e){ce(D.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1694
1694
  /**
1695
1695
  * \u963F\u91CC\u4E91 ARMS (Application Real-time Monitoring Service) browser agent.
1696
1696
  * Injects the official JS agent via next/script.
@@ -1711,11 +1711,11 @@ export function ArmsScript() {
1711
1711
  />
1712
1712
  );
1713
1713
  }
1714
- `)}function Sa(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1714
+ `)}function ha(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1715
1715
  ALIYUN_ARMS_LICENSE_KEY=
1716
1716
  ALIYUN_ARMS_APP_NAME=
1717
1717
  NEXT_PUBLIC_ARMS_PID=
1718
- `}function ha(e){ce(D.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1718
+ `}function Ea(e){ce(D.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1719
1719
  /**
1720
1720
  * \u542C\u4E91 Browser Agent (\u524D\u7AEF\u6027\u80FD\u76D1\u63A7).
1721
1721
  * Docs: https://www.tingyun.com/docs
@@ -1733,12 +1733,12 @@ export function TingYunScript() {
1733
1733
  />
1734
1734
  );
1735
1735
  }
1736
- `)}function Ea(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1736
+ `)}function va(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1737
1737
  TINGYUN_LICENSE_KEY=
1738
1738
  NEXT_PUBLIC_TINGYUN_APP_KEY=
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
1739
+ `}async function Wo(e,t,n="global"){let o=Ho(t);if(!o||o.id==="none")return;let s=D.join(e,"apps","web");if(!ue.existsSync(s))return;let r=o.id;try{switch(r){case"sentry":da(s),un(s,dn.sentry),dt(e,ua());return;case"datadog":ma(s),un(s,dn.datadog),dt(e,ga());return;case"bugsnag":fa(s),un(s,dn.bugsnag),dt(e,ya());return;case"aliyun-arms":Sa(s),dt(e,ha());return;case"tingyun":Ea(s),dt(e,va());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 Xo(e){return Ct.find(t=>t.id===e)}var hd=Ct.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function zo(e,t,n="global"){let o=Xo(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 ba from"path";async function Jo(e,t){let n=ba.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)+`
1740
+ `)}}import xt from"fs";import Qe from"path";import{fileURLToPath as _a}from"url";var Pa=_a(import.meta.url),Qo=Qe.dirname(Pa);function wa(){let e=[Qe.join(Qo,"..","templates","orm","drizzle"),Qe.join(Qo,"..","..","templates","orm","drizzle")];for(let t of e)if(xt.existsSync(t))return t;return null}function Zo(e,t){xt.mkdirSync(t,{recursive:!0});for(let n of xt.readdirSync(e,{withFileTypes:!0})){let o=Qe.join(e,n.name),s=Qe.join(t,n.name);n.isDirectory()?Zo(o,s):xt.copyFileSync(o,s)}}async function es(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=wa();if(!o)return{applied:!1,reason:"Drizzle template directory not found in package \u2014 bundling error"};let s=Qe.join(e,"packages","platform","db-drizzle");return Zo(o,s),{applied:!0}}import me from"fs";import ut from"path";var Aa=["stripe","lemonsqueezy","chinapay","polar"];function ts(e){me.existsSync(e)&&me.rmSync(e,{recursive:!0,force:!0})}function Ia(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function Ca(e,t){let n=ut.join(e,".env.example");me.existsSync(n)?me.appendFileSync(n,`
1741
+ `+t):me.writeFileSync(n,t)}function xa(e){switch(e){case"stripe":return`# Stripe
1742
1742
  STRIPE_SECRET_KEY=
1743
1743
  STRIPE_WEBHOOK_SECRET=
1744
1744
  `;case"lemon":return`# Lemon Squeezy
@@ -1753,14 +1753,14 @@ CHINAPAY_WECHAT_ENABLED=true
1753
1753
  CHINAPAY_APP_ID=
1754
1754
  CHINAPAY_APP_SECRET=
1755
1755
  CHINAPAY_ALIPAY_ENABLED=true
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,`
1756
+ `}}async function ns(e,t){let n=ut.join(e,"packages","commerce","billing");if(!me.existsSync(n))return;if(t==="none"){ts(n);return}let o=ut.join(n,"src"),s=new Set(Ia(t));for(let i of Aa)s.has(i)||ts(ut.join(o,i));let r=ut.join(o,"checkout","types.ts");if(me.existsSync(r)){let i=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",a=me.readFileSync(r,"utf8"),c=a.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${i}";`);c!==a&&me.writeFileSync(r,c)}Ca(e,xa(t))}import _e from"fs";import Ze from"path";var rs=new Set(["siliconflow","volcengine-ark","bailian","moonshot","sensetime"]),gn=/@sailor:([^\s*]+)/;function Ra(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=>rs.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 os(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function ss(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function is(e,t){let n=e.split(`
1757
+ `),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:p}=Ra(a[1],t);if(c==="registry-entries"){o.push(s?ss(i):os(i)),r++;continue}if(p){let u=s?ss(i):os(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 ka(o.join(`
1758
+ `),t)}function ka(e,t){let{providerIds:n,customEndpoint:o}=t,s=new Set;for(let p of n)["openai","anthropic","google","mistral","xai"].includes(p)&&s.add(p),s.add(p.replace(/-/g,"_")),s.add(p);o&&s.add("custom");let r=/createProviderRegistry\(\{([\s\S]*?)\}\)/,i=e.match(r);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?s.has(d[1]):!0}).join(`
1760
+ `);return e.replace(r,`createProviderRegistry({${c}})`)}function Ta(e,t){let n=Ze.join(t,"registry.ts.template"),o=_e.readFileSync(n,"utf-8");return is(o,e)}function Na(e,t){let n=Ze.join(t,".env.example.template"),o=_e.readFileSync(n,"utf-8");return is(o,e)}async function as(e,t,n){let o=Ta(t,n),s=Na(t,n),r=Ze.join(e,"packages/ai/agents/src");await _e.promises.mkdir(r,{recursive:!0}),await _e.promises.writeFile(Ze.join(r,"registry.ts"),o),await _e.promises.appendFile(Ze.join(e,".env.example"),`
1761
+ `+s);let i={ai:"latest"},{providerIds:a,customEndpoint:c}=t;(a.includes("openai")||c||a.some(u=>rs.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 cs(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()?cs(s,t):t(s)}}async function ps(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)+`
1763
+ `)}let a=g.join(s,"src","index.ts");y.existsSync(a)&&y.writeFileSync(a,`
1764
1764
  export const prisma = {} as any;
1765
1765
  export const db = {} as any;
1766
1766
  export type PrismaClient = any;
@@ -1806,7 +1806,7 @@ export type UsageAggregate = any;
1806
1806
  export type UsageLedgerEntry = any;
1807
1807
  export type UsageType = any;
1808
1808
  export type UsageLedgerSource = any;
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,`
1809
+ `)}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 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,`
1810
1810
  import React from 'react';
1811
1811
  export function useTranslations(namespace?: string): any { return (key: string) => key; }
1812
1812
  export function useLocale() { return 'en'; }
@@ -1847,14 +1847,14 @@ export * from './mock-i18n';
1847
1847
  export { default } from './mock-i18n';
1848
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": {
1849
1849
  "next-intl": ["./src/lib/mock-i18n"],
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)+`
1850
+ "next-intl/*": ["./src/lib/mock-i18n"],`);y.writeFileSync(h,m)}}catch{}let f=g.join(a,"src");y.existsSync(f)&&cs(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)+`
1851
1851
  `)}}}}y.writeFileSync(n,JSON.stringify(o,null,2)+`
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 {
1852
+ `)}function b(e){try{y.rmSync(e,{recursive:!0,force:!0})}catch{}}function Oa(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)+`
1853
+ `)}function ls(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/src/components/cookie-consent-banner.tsx")),b(g.join(e,"apps/landing/src/components/__tests__/cookie-consent-banner.test.tsx")),b(g.join(e,"apps/landing/src/lib/cookie-consent.ts")),b(g.join(e,"apps/landing/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/src/app/[lang]/(legal)/legal")),b(g.join(e,"apps/landing/src/lib/legal-documents.ts")),b(g.join(e,"apps/landing/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(b(g.join(e,"packages/ops/china-compliance")),b(g.join(e,"apps/landing/src/components/icp-footer.tsx")),b(g.join(e,"apps/landing/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")),Oa(g.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import et from"fs";import ds from"path";var us=/^--\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/m;function La(e){let t=us.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 Ua(e){return e.replace(us,"").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(s=>s.isDirectory()).sort((s,r)=>s.name.localeCompare(r.name));for(let s of o){let r=ds.join(e,s.name),i=ds.join(r,"migration.sql");if(!et.existsSync(i)){n.skipped.push(s.name);continue}let a=et.readFileSync(i,"utf8"),c=La(a);if(!c){n.skipped.push(s.name);continue}let p=t[c.flag];if(p!==void 0&&c.values.includes(p)){et.writeFileSync(i,Ua(a)),n.kept.push(s.name);continue}et.rmSync(r,{recursive:!0,force:!0}),n.removed.push(s.name)}return n}import{getSchema as Ma,printSchema as Da}from"@mrleebo/prisma-ast";var Fa=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function ja(e){return e.type==="comment"&&e.text.trim().startsWith("//")}function Ba(e){let t=Fa.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 Va(e,t){for(let n=t-1;n>=0;n--){let o=e[n];if(o.type==="comment"){let s=Ba(o.text);if(s)return{annIndex:n,parsed:s};continue}break}return null}function Ka(e){return e.type==="model"||e.type==="enum"}function yn(e,t){let n=Ma(e),o=new Set;for(let a=0;a<n.list.length;a++){let c=n.list[a];if(!Ka(c))continue;let p=Va(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(ja(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 Da({type:"schema",list:r})}import tt from"fs";import gs 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 ms(e){return Rt.find(t=>t.id===e)}var Yd=Rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function fs(e){return tt.existsSync(e)?tt.readFileSync(e,"utf-8"):null}function $a(e,t){let n=gs.join(e,".env.example"),o=fs(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(`
1854
+ `);tt.appendFileSync(n,r)}function Ya(e,t,n){let o=gs.join(e,".env.example"),s=fs(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}"
1855
+ `)}async function ys(e,t,n){let o=Re(e,"queue");if(t==="none"){o&&tt.rmSync(o,{recursive:!0,force:!0});return}let s=ms(t);if(!s)throw new Error(`Unknown queue provider "${t}". Valid ids: ${Rt.map(r=>r.id).join(", ")}`);o&&($a(e,s),Ya(e,"QUEUE_PROVIDER",t))}import ge from"fs";import Pe from"path";import{fileURLToPath as qa}from"url";var Ga=qa(import.meta.url),Ss=Pe.dirname(Ga),Ha=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|toml|py)$/,Wa=["backends/gateway","infra","e2e","tests"];function Xa(){let e=[Pe.join(Ss,"..","templates"),Pe.join(Ss,"..","..","templates")];for(let t of e)if(ge.existsSync(t))return t;return e[0]}async function hs(e,t){let n=Xa(),o=[],s=[],r=[...Wa,...t.withWorkflows?["workflows"]:[],...t.withPythonBackend?["backends/python"]:[]];for(let i of r){let a=Pe.join(n,i);if(!ge.existsSync(a)){s.push(i);continue}let c=Pe.join(e,i);Es(a,c),vs(c,{"{PRODUCT_NAME}":t.projectName}),o.push(i)}return{applied:o,skipped:s}}function Es(e,t){ge.mkdirSync(t,{recursive:!0});for(let n of ge.readdirSync(e,{withFileTypes:!0})){let o=Pe.join(e,n.name),s=Pe.join(t,n.name);n.isDirectory()?Es(o,s):ge.existsSync(s)||ge.copyFileSync(o,s)}}function vs(e,t){for(let n of ge.readdirSync(e,{withFileTypes:!0})){let o=Pe.join(e,n.name);if(n.isDirectory()){vs(o,t);continue}if(!Ha.test(n.name))continue;let s=ge.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&&ge.writeFileSync(o,s)}}import nt from"fs";import _s 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 bs(e){return kt.find(t=>t.id===e)}var tu=kt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ps(e){return nt.existsSync(e)?nt.readFileSync(e,"utf-8"):null}function za(e,t){let n=_s.join(e,".env.example"),o=Ps(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(`
1856
+ `);nt.appendFileSync(n,r)}function Ja(e,t,n){let o=_s.join(e,".env.example"),s=Ps(o);if(s===null)return;let r=new RegExp(`^${t}=.*$`,"m");r.test(s)?nt.writeFileSync(o,s.replace(r,`${t}="${n}"`)):nt.appendFileSync(o,`${t}="${n}"
1857
+ `)}async function ws(e,t,n){let o=Re(e,"search");if(t==="none"){o&&nt.rmSync(o,{recursive:!0,force:!0});return}let s=bs(t);if(!s)throw new Error(`Unknown search provider "${t}". Valid ids: ${kt.map(r=>r.id).join(", ")}`);o&&(za(e,s),Ja(e,"SEARCH_PROVIDER",t))}import we from"fs";import De from"path";function Qa(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 Za(e){try{let t=we.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 ec(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
1858
1858
  const admin = await prisma.user.create({
1859
1859
  data: {
1860
1860
  clerkId: "user_mock_admin",
@@ -1885,7 +1885,7 @@ export { default } from './mock-i18n';
1885
1885
  console.log("\\u2713 Created admin user:", admin.email);
1886
1886
  } catch (err) {
1887
1887
  console.warn("\\u26A0 Admin user creation skipped:", (err as Error).message);
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 }> = [];
1888
+ }`}function tc(e,t){let n=t.has("Tenant"),o=t.has("User"),s=t.has("Project"),r=ec(e,o),i=n?` let tenants: Array<{ id: string; name: string }> = [];
1889
1889
  try {
1890
1890
  tenants = await Promise.all([
1891
1891
  prisma.tenant.create({
@@ -1902,7 +1902,7 @@ export { default } from './mock-i18n';
1902
1902
  } catch (err) {
1903
1903
  console.warn("\\u26A0 Tenant creation skipped:", (err as Error).message);
1904
1904
  }`:` const tenants: Array<{ id: string; name: string }> = [];
1905
- console.log("\\u2139 No Tenant model in schema \u2014 skipping tenant seed.");`,a=r&&n?` for (const tenant of tenants) {
1905
+ console.log("\\u2139 No Tenant model in schema \u2014 skipping tenant seed.");`,a=s&&n?` for (const tenant of tenants) {
1906
1906
  try {
1907
1907
  await prisma.project.createMany({
1908
1908
  data: [
@@ -1938,7 +1938,7 @@ async function main(): Promise<void> {
1938
1938
  ${i}
1939
1939
 
1940
1940
  // --- Admin user ------------------------------------------------------
1941
- ${s}
1941
+ ${r}
1942
1942
 
1943
1943
  // --- Sample projects per tenant --------------------------------------
1944
1944
  ${a}
@@ -1954,12 +1954,12 @@ main()
1954
1954
  .finally(async () => {
1955
1955
  await prisma.$disconnect();
1956
1956
  });
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(`
1957
+ `}function nc(e){if(we.existsSync(e))try{let t=we.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};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 As(e,t){let n=Qa(e);if(n)try{let o=De.join(n.packageDir,"prisma","schema.prisma"),s=Za(o),r=tc(t,s),i=De.dirname(n.seedPath);we.existsSync(i)||we.mkdirSync(i,{recursive:!0}),we.writeFileSync(n.seedPath,r),nc(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 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:""}],du=Tt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Is(e){return Tt.find(t=>t.id===e)}var oc="@nebutra/sms",sc={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 ic(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
1960
1960
  `);return`${t}
1961
1961
  ${n}
1962
- `}var ic=`/**
1962
+ `}var ac=`/**
1963
1963
  * Inputs for the \`sendSms\` wrapper. Keep this surface portable across
1964
1964
  * providers \u2014 provider-specific options belong in the wrapper itself.
1965
1965
  */
@@ -1979,7 +1979,7 @@ export interface SendSmsResult {
1979
1979
  provider: string;
1980
1980
  raw?: unknown;
1981
1981
  }
1982
- `;function ac(){return`import twilio from "twilio";
1982
+ `;function cc(){return`import twilio from "twilio";
1983
1983
  import type { SendSmsInput, SendSmsResult } from "./types";
1984
1984
 
1985
1985
  let client: ReturnType<typeof twilio> | null = null;
@@ -2014,7 +2014,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2014
2014
  }
2015
2015
 
2016
2016
  export type { SendSmsInput, SendSmsResult } from "./types";
2017
- `}function cc(){return`import messagebird from "messagebird";
2017
+ `}function pc(){return`import messagebird from "messagebird";
2018
2018
  import type { SendSmsInput, SendSmsResult } from "./types";
2019
2019
 
2020
2020
  let client: ReturnType<typeof messagebird> | null = null;
@@ -2052,7 +2052,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2052
2052
  }
2053
2053
 
2054
2054
  export type { SendSmsInput, SendSmsResult } from "./types";
2055
- `}function pc(){return`import plivo from "plivo";
2055
+ `}function lc(){return`import plivo from "plivo";
2056
2056
  import type { SendSmsInput, SendSmsResult } from "./types";
2057
2057
 
2058
2058
  let client: InstanceType<typeof plivo.Client> | null = null;
@@ -2091,7 +2091,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2091
2091
  }
2092
2092
 
2093
2093
  export type { SendSmsInput, SendSmsResult } from "./types";
2094
- `}function lc(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2094
+ `}function dc(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2095
2095
  import * as $OpenApi from "@alicloud/openapi-client";
2096
2096
  import type { SendSmsInput, SendSmsResult } from "./types";
2097
2097
 
@@ -2140,7 +2140,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2140
2140
  }
2141
2141
 
2142
2142
  export type { SendSmsInput, SendSmsResult } from "./types";
2143
- `}function dc(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2143
+ `}function uc(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2144
2144
  import type { SendSmsInput, SendSmsResult } from "./types";
2145
2145
 
2146
2146
  const SmsClient = tencentcloud.sms.v20210111.Client;
@@ -2205,7 +2205,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2205
2205
  }
2206
2206
 
2207
2207
  export type { SendSmsInput, SendSmsResult } from "./types";
2208
- `}function uc(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2208
+ `}function mc(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2209
2209
  import Yunpian from "yunpian-nodejs-sdk";
2210
2210
  import type { SendSmsInput, SendSmsResult } from "./types";
2211
2211
 
@@ -2257,13 +2257,13 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2257
2257
  }
2258
2258
 
2259
2259
  export type { SendSmsInput, SendSmsResult } from "./types";
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(`
2260
+ `}function gc(e){switch(e){case"twilio":return cc();case"messagebird":return pc();case"plivo":return lc();case"aliyun-sms":return dc();case"tencent-sms":return uc();case"yunpian":return mc();case"none":return`export {};
2261
+ `}}function fc(e){let t={};for(let o of e.pkgs??[]){let s=sc[o];s&&(t[o]=s)}let n={name:oc,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 Cs(e,t,n="global"){if(t==="none")return;let o=Is(t);if(!o)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${Tt.map(i=>i.id).join(", ")}`);let s=Fe.join(e,"packages","sms");if(!Ae.existsSync(s))return;let r=Fe.join(s,"src");Ae.existsSync(r)&&Ae.rmSync(r,{recursive:!0,force:!0});try{Sn(Fe.join(s,"package.json"),fc(o)),Sn(Fe.join(r,"types.ts"),ac),Sn(Fe.join(r,"index.ts"),gc(o.id)),rc(e,ic(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 yc(e,t){let n=je.join(e,".env.example");Be.existsSync(n)?Be.appendFileSync(n,`
2263
+ `+t):Be.writeFileSync(n,t)}function Sc(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
2264
2264
  `);return`${t}
2265
2265
  ${n}
2266
- `}var Sc=`/**
2266
+ `}var hc=`/**
2267
2267
  * Inputs for the \`uploadFile\` wrapper. Keep this surface portable across
2268
2268
  * providers \u2014 provider-specific options belong in the wrapper itself.
2269
2269
  */
@@ -2289,7 +2289,7 @@ export interface SignedUrlOptions {
2289
2289
  operation?: "get" | "put";
2290
2290
  contentType?: string;
2291
2291
  }
2292
- `;function hc(){return`/**
2292
+ `;function Ec(){return`/**
2293
2293
  * @${Ve.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
2294
2294
  *
2295
2295
  * Docs: https://developers.cloudflare.com/r2/api/s3/api/
@@ -2353,7 +2353,7 @@ export async function getSignedUrl(
2353
2353
  }
2354
2354
 
2355
2355
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2356
- `}function Ec(){return`/**
2356
+ `}function vc(){return`/**
2357
2357
  * @${Ve.slice(1)} \u2014 AWS S3 wrapper.
2358
2358
  *
2359
2359
  * Docs: https://docs.aws.amazon.com/s3/
@@ -2418,7 +2418,7 @@ export async function getSignedUrl(
2418
2418
  }
2419
2419
 
2420
2420
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2421
- `}function vc(){return`/**
2421
+ `}function bc(){return`/**
2422
2422
  * @${Ve.slice(1)} \u2014 Supabase Storage wrapper.
2423
2423
  *
2424
2424
  * Docs: https://supabase.com/docs/guides/storage
@@ -2481,7 +2481,7 @@ export async function getSignedUrl(
2481
2481
  }
2482
2482
 
2483
2483
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2484
- `}function bc(){return`/**
2484
+ `}function _c(){return`/**
2485
2485
  * @${Ve.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2486
2486
  *
2487
2487
  * Docs: https://help.aliyun.com/product/31815.html
@@ -2528,7 +2528,7 @@ export async function getSignedUrl(
2528
2528
  }
2529
2529
 
2530
2530
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2531
- `}function _c(){return`/**
2531
+ `}function Pc(){return`/**
2532
2532
  * @${Ve.slice(1)} \u2014 \u817E\u8BAF\u4E91 COS wrapper via cos-nodejs-sdk-v5.
2533
2533
  *
2534
2534
  * Docs: https://cloud.tencent.com/document/product/436
@@ -2583,7 +2583,7 @@ export async function getSignedUrl(
2583
2583
  }
2584
2584
 
2585
2585
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2586
- `}function Pc(){return`/**
2586
+ `}function wc(){return`/**
2587
2587
  * @${Ve.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2588
2588
  *
2589
2589
  * Docs: https://developer.qiniu.com/kodo
@@ -2651,9 +2651,9 @@ export async function getSignedUrl(
2651
2651
  }
2652
2652
 
2653
2653
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
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";
2654
+ `}function Ac(e){switch(e){case"r2":return Ec();case"s3":return vc();case"supabase-storage":return bc();case"aliyun-oss":return _c();case"tencent-cos":return Pc();case"qiniu":return wc();case"none":return`export {};
2655
+ `}}function Ic(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 xs(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 s=je.join(e,"packages","storage"),r=je.join(s,"src");Be.existsSync(r)&&Be.rmSync(r,{recursive:!0,force:!0}),hn(je.join(s,"package.json"),Ic(o)),hn(je.join(r,"types.ts"),hc),hn(je.join(r,"index.ts"),Ac(o.id)),yc(e,Sc(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 Rs(e){return Nt.find(t=>t.id===e)}var bu=Nt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function ks(e,t,n="global"){let o=Rs(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 Ke from"fs";import mt from"path";function Cc(e){return`import { brand } from "@nebutra/brand/metadata";
2657
2657
  import Link from "next/link";
2658
2658
 
2659
2659
  export default function WelcomePage() {
@@ -2763,21 +2763,21 @@ function Step({
2763
2763
  </li>
2764
2764
  );
2765
2765
  }
2766
- `}function Cc(e={}){return`
2766
+ `}function xc(e={}){return`
2767
2767
  ## What you can do next
2768
2768
 
2769
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(`
2770
2770
  `)}
2771
- `}function xc(e=[]){return e.length===0?"":`
2771
+ `}function Rc(e=[]){return e.length===0?"":`
2772
2772
  ## Production readiness holds
2773
2773
 
2774
2774
  Do not enable these in production until provider credentials, adapter wiring, and the integration contract are verified:
2775
2775
 
2776
- ${e.map(n=>{let o=Xe(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 ${Ee(n.status)}`}).join(`
2777
2777
  `)}
2778
2778
 
2779
2779
  Review the package readiness matrix before handoff: [docs/package-status.md](docs/package-status.md)
2780
- `}function Rc(e,t,n=[],o={}){return`# Next steps \u2014 ${e}
2780
+ `}function kc(e,t,n=[],o={}){return`# Next steps \u2014 ${e}
2781
2781
 
2782
2782
  Region: ${t}
2783
2783
 
@@ -2803,24 +2803,24 @@ Your AI-native SaaS scaffold is ready. Complete these four steps to go from temp
2803
2803
  \`\`\`
2804
2804
 
2805
2805
  After setup, delete the welcome route at \`apps/web/src/app/[locale]/welcome/\`.
2806
- ${Cc(o)}${xc(n)}
2806
+ ${xc(o)}${Rc(n)}
2807
2807
 
2808
2808
  ## Resources
2809
2809
 
2810
2810
  - [Documentation](/docs)
2811
2811
  - [GitHub](https://github.com/nebutra/nebutra-sailor)
2812
2812
  - [Get free license (Individual/OPC)](https://nebutra.com/get-license)
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).
2816
- Upstream AGPL preserved as LICENSE-AGPL-REFERENCE.md.
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
2822
-
2823
- `))}var Uc=`Usage: create-sailor [name] [options]
2813
+ `}async function Ts(e,t){let{projectName:n,region:o,previewSelections:s=[],waveFeatures:r={}}=t;try{let i=mt.join(e,".sailor");Ke.existsSync(i)||Ke.mkdirSync(i,{recursive:!0}),Ke.writeFileSync(mt.join(i,"next-steps.md"),kc(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=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"),Cc(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 Ns(e){return e!==null&&typeof e=="object"&&"code"in e&&e.code==="ENOENT"}function Nc(e,t){for(let n of t)if(e)l(!0,{event:"warn",step:n.flag,provider:n.provider,packageStatus:n.status,message:Ee(n.status)});else{let o=Xe(n.status);process.stdout.write(gt.yellow(`\u26A0 ${n.flag}=${n.provider} ${o} \u2014 ${Ee(n.status)}
2815
+ `))}}function Oc(e,t,n){let o=$e.join(t,"packages/platform/db/prisma/schema.prisma"),s;try{s=Lt.readFileSync(o,"utf8")}catch(r){if(Ns(r)){l(e,{event:"step",step:"schema-prune",status:"skip"});return}let i=r instanceof Error?r.message:String(r);l(e,{event:"step",step:"schema-prune",status:"error",error:i});return}l(e,{event:"step",step:"schema-prune",status:"start"});try{let r=yn(s,n);Lt.writeFileSync(o,r),fn($e.join($e.dirname(o),"migrations"),n),l(e,{event:"step",step:"schema-prune",status:"ok"})}catch(r){let i=r instanceof Error?r.message:String(r);l(e,{event:"step",step:"schema-prune",status:"error",error:i})}}async function Os(e){let{resolvedTarget:t,projectName:n,resolvedPm:o,opts:s,useJson:r,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:fe,accessGate:pe,mcp:Z,waveToggles:j,previewSelections:K,config:C}=i,H={auth:f,payment:h,"billing-mode":M,idp:fe,template:"saas","access-gate":pe};l(r,{event:"step",step:"clone",status:"start"}),await Uo(t),l(r,{event:"step",step:"clone",status:"ok"}),l(r,{event:"step",step:"package",status:"start"}),await Jo(t,n),l(r,{event:"step",step:"package",status:"ok"}),l(r,{event:"step",step:"config",status:"start"}),await co(t,C),l(r,{event:"step",step:"config",status:"ok"}),l(r,{event:"step",step:"governance-lints",status:"start"});let le=await Do(t,C);l(r,{event:"step",step:"governance-lints",status:"ok",lints:le.lints}),l(r,{event:"step",step:"prune",status:"start"}),await ps(t,C),l(r,{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(Ns(I))l(r,{event:"step",step:"schema-prune",status:"skip"});else{let x=I instanceof Error?I.message:String(I);l(r,{event:"step",step:"schema-prune",status:"error",error:x})}}if(k!==void 0){l(r,{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(r,{event:"step",step:"schema-prune",status:"ok"})}catch(I){let x=I instanceof Error?I.message:String(I);l(r,{event:"step",step:"schema-prune",status:"error",error:x})}}}if(l(r,{event:"step",step:"auth",choice:f,status:"start"}),await zn(t,f),l(r,{event:"step",step:"auth",choice:f,status:"ok"}),E.length>0?(l(r,{event:"step",step:"social-login",providers:E,status:"start"}),await Qn(t,E,f),l(r,{event:"step",step:"social-login",providers:E,status:"ok"})):l(r,{event:"step",step:"social-login",status:"skip"}),l(r,{event:"step",step:"db",choice:u,status:"start"}),await uo(t,u,n),u!=="none"){let v=rt(d);v&&(await mo(t,v,n),l(r,{event:"step",step:"db-host",choice:d,status:"ok"}))}if(l(r,{event:"step",step:"db",choice:u,status:"ok"}),p==="drizzle"){l(r,{event:"step",step:"orm",choice:"drizzle",status:"start"});let v=await es(t,"drizzle",u);l(r,{event:"step",step:"orm",choice:"drizzle",status:v.applied?"ok":"skip",...v.reason?{reason:v.reason}:{}})}if(l(r,{event:"step",step:"payment",choice:h,status:"start"}),await ns(t,h),l(r,{event:"step",step:"payment",choice:h,status:"ok"}),await vo(t,i.email,c),r&&l(!0,{event:"step",step:"email",choice:i.email,status:"ok"}),await xs(t,i.storage,c),r&&l(!0,{event:"step",step:"storage",choice:i.storage,status:"ok"}),await Wo(t,i.monitoring,c),r&&l(!0,{event:"step",step:"monitoring",choice:i.monitoring,status:"ok"}),await Wn(t,i.analytics,c),r&&l(!0,{event:"step",step:"analytics",choice:i.analytics,status:"ok"}),await Cs(t,i.sms,c),r&&l(!0,{event:"step",step:"sms",choice:i.sms,status:"ok"}),await ys(t,i.queue,c),r&&l(!0,{event:"step",step:"queue",choice:i.queue,status:"ok"}),await ws(t,i.search,c),r&&l(!0,{event:"step",step:"search",choice:i.search,status:"ok"}),await no(t,i.cache,c),r&&l(!0,{event:"step",step:"cache",choice:i.cache,status:"ok"}),await zo(t,i.notifications,c),r&&l(!0,{event:"step",step:"notifications",choice:i.notifications,status:"ok"}),await ks(t,i.webhooks,c),r&&l(!0,{event:"step",step:"webhooks",choice:i.webhooks,status:"ok"}),await io(t,i.cms,c),r&&l(!0,{event:"step",step:"cms",choice:i.cms,status:"ok"}),await xo(t,i.featureFlags,c),r&&l(!0,{event:"step",step:"feature-flags",choice:i.featureFlags,status:"ok"}),await so(t,i.captcha,c),r&&l(!0,{event:"step",step:"captcha",choice:i.captcha,status:"ok"}),await $o(t,Z),r&&l(!0,{event:"step",step:"mcp",mode:Z,status:"ok"}),await qo(t,G,_),r&&l(!0,{event:"step",step:"metering",mode:G,status:"ok"}),l(r,{event:"step",step:"prune-wave-features",status:"start"}),ls(t,j),l(r,{event:"step",step:"prune-wave-features",status:"ok",toggles:j}),C.orm==="prisma"&&C.database!=="none"?Oc(r,t,H):l(r,{event:"step",step:"schema-prune",status:"skip"}),l(r,{event:"step",step:"billing-mode",choice:M,status:"ok"}),l(r,{event:"step",step:"idp",choice:fe,status:"ok"}),await ao(t,c),r&&l(!0,{event:"step",step:"compliance",region:c,status:"ok"}),await Io(t),await As(t,f),await Ts(t,{projectName:n,region:c,previewSelections:K,waveFeatures:j}),C.aiMode!=="none"){l(r,{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 as(t,v,k),l(r,{event:"step",step:"ai-providers",status:"ok"})}else l(r,{event:"step",step:"ai-providers",status:"skip"});l(r,{event:"step",step:"docs",status:"start"}),P!=="none"?(await yo(t,{framework:P,projectName:n}),l(r,{event:"step",step:"docs",framework:"fumadocs",requested:P,status:"ok"})):l(r,{event:"step",step:"docs",status:"skip"}),l(r,{event:"step",step:"deploy-target",status:"start"}),m!=="none"&&await Vn(t,m),await Bn(t,C.deployTargets),l(r,{event:"step",step:"deploy-target",status:"ok",targets:C.deployTargets});let w={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""};l(r,{event:"step",step:"env",status:"start"}),await Po(t,w),l(r,{event:"step",step:"env",status:"ok"}),l(r,{event:"step",step:"scaffold-extras",status:"start"});let ye=await hs(t,{projectName:n,withWorkflows:!!s.withWorkflows,withPythonBackend:!!s.withPythonBackend});l(r,{event:"step",step:"scaffold-extras",status:"ok",applied:ye.applied,skipped:ye.skipped}),l(r,{event:"step",step:"license",status:"start"});try{let v=Ko(t,{projectName:n,cliVersion:X});l(r,{event:"step",step:"license",status:"ok",tier:"mit-scaffold",wrote:v.wrote}),r||process.stdout.write(gt.dim(` License: MIT \u2014 commercial use, closed source, no fee, no attribution.
2816
+ Upstream terms preserved as LICENSE-UPSTREAM-REFERENCE.md.
2817
+ `))}catch(v){l(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?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:r?"ignore":"inherit"}),l(r,{event:"step",step:"install",status:"ok"})}catch(I){let x=I instanceof Error?I.message:String(I);r?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(r,{event:"step",step:"install",status:"skip"});if(s.git!==!1){r&&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(r,{event:"step",step:"git-init",status:"ok"})}catch(v){let k=v instanceof Error?v.message:String(v);r?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(r,{event:"step",step:"git-init",status:"skip"});let Se=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&&Nc(r,K),r?l(!0,{event:"done",status:"ok",elapsedSec:Se,targetDir:t,previewSelections:K,waveFeatures:j}):qn({elapsedSec:Se,targetDir:t,skippedInstall:s.install===!1,previewSelections:K,waveFeatures:j});try{Tc({pkg:{name:"create-sailor",version:X},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}}import Lc from"cfonts";import Uc from"picocolors";function Ls(){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}Lc.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(Uc.dim(` AI-Native SaaS Template \xB7 v${X} \xB7 nebutra.com
2822
+
2823
+ `))}var Mc=`Usage: create-sailor [name] [options]
2824
2824
 
2825
2825
  Arguments:
2826
2826
  name project directory (default: ./my-saas-app)
@@ -2891,18 +2891,18 @@ Examples:
2891
2891
  $ npx create-sailor@latest my-app --region=cn --auth=clerk
2892
2892
  $ npx create-sailor@latest my-app --region=hybrid --ai=openai,deepseek
2893
2893
  $ npm create sailor@latest --dry-run --region=cn
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(`
2894
+ `;function Us(){process.stdout.write(Mc)}import Ut from"picocolors";function Ms(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Dc(e){let t=Ms()?"\u25B8":"->",n=`[${e.index}/${e.total}]`,o=e.label.padEnd(18," ");return Ms()?`${Ut.dim(n)} ${Ut.bold(o)} ${Ut.dim(t)} ${Ut.cyan(e.value)}`:`${n} ${o} ${t} ${e.value}`}function Ds(e){process.stdout.write(Dc(e)+`
2895
+ `)}import{existsSync as Fc,mkdirSync as Fs,writeFileSync as js}from"fs";import{homedir as Bs,platform as jc}from"os";import{join as ft}from"path";function Bc(){if(jc()==="win32"){let t=process.env.LOCALAPPDATA||ft(Bs(),"AppData","Local");return ft(t,"nebutra")}let e=process.env.XDG_CONFIG_HOME;return e?ft(e,"nebutra"):ft(Bs(),".config","nebutra")}function Vc(){let e=process.env.NEBUTRA_TELEMETRY;return e==="0"||e==="false"||e==="no"}function Vs(){if(!process.stderr.isTTY||!process.stdin.isTTY||process.env.CI)return;let e=Bc(),t=ft(e,"first-run-acked");try{if(Fc(t))return}catch{return}if(Vc()){try{Fs(e,{recursive:!0}),js(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{Fs(e,{recursive:!0}),js(t,"")}catch{}}function Ye(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2897
+ `)}function $c(e,t,n,o,s){let{region:r,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:fe}=t,{email:pe,storage:Z,monitoring:j,analytics:K,sms:C,queue:H,search:le,cache:w,notifications:ye,webhooks:qe,cms:Ge,featureFlags:Se,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}`}`,...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}`]:[],...ye!=="none"?[`notifications \u2192 configure ${ye}`]:[],...qe!=="none"?[`webhooks \u2192 configure ${qe}`]:[],...Ge!=="none"?[`cms \u2192 configure ${Ge}`]:[],...Se!=="none"?[`feature-flags \u2192 configure ${Se}`]:[],...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)Ye(!0,{event:"plan",action:x});for(let x of fe)Ye(!0,{event:"warn",step:x.flag,provider:x.provider,packageStatus:x.status});Ye(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2898
2898
  `+F.bold(`Dry run \u2014 planned actions:
2899
2899
  `));for(let x of I)process.stdout.write(` \u2022 ${x}
2900
- `);if(ge.length>0){process.stdout.write(`
2900
+ `);if(fe.length>0){process.stdout.write(`
2901
2901
  `+F.bold(F.yellow(`Preview-status providers selected:
2902
- `)));for(let x of ge)process.stdout.write(F.yellow(`\u26A0 ${x.flag}=${x.provider}
2902
+ `)));for(let x of fe)process.stdout.write(F.yellow(`\u26A0 ${x.flag}=${x.provider}
2903
2903
  `))}process.stdout.write(F.dim(`
2904
2904
  No files were written.
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(`
2905
+ `))}}async function Yc(){let e=Cn();e.parse(process.argv);let t=e.opts(),[n]=e.args;t.help&&(Us(),process.exit(0));let o=!!t.json,s=!!t.dryRun,r=!!t.yes,i=r||!process.stdin.isTTY;if(o||(Vs(),Ls()),Ye(o,{event:"start",version:X}),!t.pm)try{Kc("pnpm --version",{stdio:"ignore"})}catch{o||process.stderr.write(`
2906
2906
  ${F.red("\u2718")} ${F.bold("pnpm is required")} but was not found on PATH.
2907
2907
 
2908
2908
  The scaffold uses pnpm workspaces + Turborepo. Install pnpm first:
@@ -2911,11 +2911,11 @@ The scaffold uses pnpm workspaces + Turborepo. Install pnpm first:
2911
2911
  Then retry: ${F.cyan("pnpm dlx create-sailor@latest")}
2912
2912
  (or pass ${F.dim("--pm=npm")} if you know workspace:* won't resolve in your setup)
2913
2913
 
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(`
2914
+ `),Ye(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 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=$s.basename($s.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)=>{Ds({index:S+1,total:_.length,label:f,value:E})}),s&&($c(o,d,c,u,t),process.exit(0));let h=async()=>{process.stdout.write(`
2916
2916
  `+F.red(`\u2718 Cancelled
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(`
2917
+ `)),Ks.existsSync(c)&&await ot.confirm({message:`Cleanup partial install at ${c}?`,initialValue:!0})===!0&&(Ks.rmSync(c,{recursive:!0,force:!0}),process.stdout.write(F.dim(` \u2713 Removed ${c}
2918
+ `))),process.exit(130)};process.on("SIGINT",h);try{await Os({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(`
2919
2919
  \u2718 Failed: ${E}
2920
- `)),process.exit(1)}}$c().catch(e=>{process.stderr.write(String(e)+`
2920
+ `)),process.exit(1)}}Yc().catch(e=>{process.stderr.write(String(e)+`
2921
2921
  `),process.exit(1)});