create-sailor 1.9.5 → 1.9.6

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 (60) hide show
  1. package/README.md +10 -8
  2. package/dist/index.js +136 -137
  3. package/package.json +16 -14
  4. package/templates/backends/gateway/package.json +1 -1
  5. package/templates/docs/docusaurus/package.json +1 -1
  6. package/templates/docs/fumadocs/package.json +1 -1
  7. package/templates/docs/mintlify/package.json +1 -1
  8. package/templates/docs/nextra/package.json +1 -1
  9. package/templates/docs/vitepress/package.json +1 -1
  10. package/templates/orm/drizzle/package.json +1 -1
  11. package/dist/aws-kms-FFRN23DK.js +0 -1
  12. package/dist/bowser-2VXD6AQS.js +0 -11
  13. package/dist/chunk-5ECPN42W.js +0 -1
  14. package/dist/chunk-6MSNEPUX.js +0 -0
  15. package/dist/chunk-A3H5SUSR.js +0 -8
  16. package/dist/chunk-AN6QWW3N.js +0 -1
  17. package/dist/chunk-CVCZBECH.js +0 -1
  18. package/dist/chunk-GA44DNS2.js +0 -1
  19. package/dist/chunk-IYWUY3VA.js +0 -1
  20. package/dist/chunk-LDZWCNWB.js +0 -0
  21. package/dist/chunk-M3NEWJ7L.js +0 -1
  22. package/dist/chunk-MGGNSWUA.js +0 -3
  23. package/dist/chunk-MYIHTCRS.js +0 -4
  24. package/dist/chunk-PA4CKDRJ.js +0 -1
  25. package/dist/chunk-QSLKOXQ6.js +0 -1
  26. package/dist/chunk-S4HCBMFP.js +0 -1
  27. package/dist/chunk-SYWJHPRX.js +0 -0
  28. package/dist/chunk-TW5BOTVX.js +0 -0
  29. package/dist/chunk-UWHWNXNX.js +0 -19
  30. package/dist/chunk-WJLTO7JW.js +0 -0
  31. package/dist/chunk-X6LE6K3W.js +0 -0
  32. package/dist/chunk-XE3I3HCZ.js +0 -40
  33. package/dist/chunk-Z4YWESTY.js +0 -2
  34. package/dist/chunk-ZIBRKYXP.js +0 -23
  35. package/dist/chunk-ZJ3BTCD6.js +0 -17
  36. package/dist/credits-UUPQKRQZ.js +0 -2802
  37. package/dist/dist-23KDUT4O.js +0 -1
  38. package/dist/dist-ZZCU5PKC.js +0 -5
  39. package/dist/dist-es-7HF5URFJ.js +0 -1
  40. package/dist/dist-es-BORZTE76.js +0 -1
  41. package/dist/dist-es-CN2GMFBK.js +0 -1
  42. package/dist/dist-es-FQ6CEUEU.js +0 -1
  43. package/dist/dist-es-FSE4MSDA.js +0 -5
  44. package/dist/dist-es-H47VUS6Q.js +0 -2
  45. package/dist/dist-es-JCIK4C4M.js +0 -2
  46. package/dist/dist-es-MFZXYPBY.js +0 -1
  47. package/dist/dist-es-PREZ4TU2.js +0 -1
  48. package/dist/dist-es-TCZQ4KMP.js +0 -2
  49. package/dist/dist-es-Y7VP7FI6.js +0 -2
  50. package/dist/dist-es-YN4LRIZR.js +0 -5
  51. package/dist/event-streams-TNY7XPBF.js +0 -1
  52. package/dist/loadSso-2XZQIDZP.js +0 -1
  53. package/dist/loadSso-FBBI5PDJ.js +0 -1
  54. package/dist/local-6WWVOMA7.js +0 -1
  55. package/dist/query_compiler_fast_bg.postgresql-JA2BFVW5.js +0 -2
  56. package/dist/query_compiler_fast_bg.postgresql.wasm-base64-URHQ2Y3Y.js +0 -1
  57. package/dist/signin-CJMG23UU.js +0 -1
  58. package/dist/sso-oidc-26OCCRMC.js +0 -1
  59. package/dist/sts-4U2U3ZK4.js +0 -1
  60. package/dist/sts-CP4OREEC.js +0 -1
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import{a as Fn}from"./chunk-PA4CKDRJ.js";import"./chunk-IYWUY3VA.js";import{execSync as mp}from"child_process";import os from"fs";import*as rs from"@clack/prompts";import L from"picocolors";import{Command as ps}from"commander";import jn from"fs";import Jt from"path";import{fileURLToPath as as}from"url";function cs(){try{let t=Jt.dirname(as(import.meta.url));for(let n=0;n<4;n++){let o=Jt.join(t,"package.json");if(jn.existsSync(o)){let r=jn.readFileSync(o,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=Jt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var z=cs();var ls="create-sailor";function Bn(){let e=new ps;return e.name(ls).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(z,"-v, --version").helpOption(!1).argument("[name]","project name or path (default: my-app; use . for current 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 Qt=[{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 mt(e){return Qt.find(t=>t.id===e)}function Vn(e){return e==="cn"||e==="hybrid"?"local":"supabase"}var Re=[{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 Zt(e){let t=e==="supabase"?"supabase-storage":e;return Re.some(n=>n.id===t)?t:void 0}function $n(e){let t=Zt(e);return t?Re.find(n=>n.id===t):void 0}var wp=Re.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function qn(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function en(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 tn(e,t,n){let o=e?.trim().toLowerCase()??Vn(t),r=mt(o);if(!r){let i=Qt.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 nn(e){return e==="drizzle"?"drizzle":"prisma"}function gt(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function ft(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 on(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 ds=new Set(["gateway","direct","custom","none"]);function rn(e){if(!e)return!1;let t=e.trim().toLowerCase();return ds.has(t)}function sn(e){if(!e)return["openai"];if(rn(e))return[];let t=e.split(",").map(n=>n.trim().toLowerCase());return t.includes("none")?[]:t}function Gn(e,t){let n=e??t;return Zt(n)??n}var Yn={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function an(e,t){if(!e)return"fumadocs";let n=e.toLowerCase();if(n==="fumadocs"||n==="none")return n;if(n in Yn){let o=Yn[n];return t?process.stdout.write(JSON.stringify({event:"notice",kind:"docs-fallback",requested:n,effective:"fumadocs"})+`
3
- `):process.stdout.write(Kn.yellow(`\u26A0 ${o} support is coming in v1.2. Falling back to fumadocs.
4
- `)+Kn.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
5
- `)),"fumadocs"}return"fumadocs"}function yt(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 cn(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function Hn(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 pn(e){return e==="cn"?"wechat":"stripe"}import*as q from"@clack/prompts";import Ts from"picocolors";var ln=[{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:[]}],Tp=ln.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var us=["openai","anthropic","google"],ms=["openai"];function dn(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let n=t.length>0?t:[...us];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:[...ms];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 Ze=[{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"}],gs=new Set(Ze.map(e=>e.id));function Wn(e){return Ze.find(t=>t.id===e)}function Xn(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)gs.has(r)&&!o.has(r)&&(n.push(r),o.add(r));return n}import te from"fs";import T from"path";import{fileURLToPath as bs}from"url";var zn=["web","landing","auth","admin","design-docs","sailor-docs","router","forge","typelens","gateway","python-ai"],fs={web:"frontend",landing:"frontend",auth:"frontend",admin:"frontend","design-docs":"frontend","sailor-docs":"frontend",router:"frontend",forge:"frontend",typelens:"frontend",gateway:"edgeGateway","python-ai":"originBackend"},ys={frontend:"vercel",edgeGateway:"cloudflare-workers",originBackend:"ecs-docker"};function Ss(e){return zn.includes(e)}function hs(e){if(!Ss(e))throw new Error(`Unknown deploy service '${e}'. Deploy targets apply only to apps/backends, not packages.`)}function Es(e){return hs(e),fs[e]}function vs(e){let t=Es(e);return ys[t]}function Jn(){return Object.fromEntries(zn.map(e=>[e,vs(e)]))}var _s=bs(import.meta.url),Qn=T.dirname(_s),Ps="cloudflare-pages",ws="standalone",As="railway";function un(e,t,n,o){return{...e,web:t,landing:t,auth:t,admin:t,"design-docs":t,"sailor-docs":t,router:t,forge:t,typelens:t,gateway:n,"python-ai":o}}function Cs(){let e=[T.join(Qn,"..","templates","deploy"),T.join(Qn,"..","..","templates","deploy")];for(let t of e)if(te.existsSync(t))return t;return e[0]}function Ct(e){let t=Jn();switch(e){case"cloudflare":return un(t,Ps,"cloudflare-workers","ecs-docker");case"selfhost":return un(t,ws,"ecs-docker","ecs-docker");case"railway":return un(t,As,"railway","railway");case"none":case"vercel":return t}}function Is(e){return`DEPLOY_TARGET_${e.toUpperCase().replace(/-/g,"_")}`}async function Zn(e,t){let n=T.join(e,"backends","gateway");te.existsSync(n)&&await te.promises.copyFile(T.join(t,"wrangler.gateway.toml"),T.join(n,"wrangler.toml"))}async function eo(e,t){let n=T.join(e,".env.example"),o;try{o=await te.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])=>`${Is(i)}="${a}"`)].join(`
2
+ import{execSync as gp}from"child_process";import os from"fs";import*as rs from"@clack/prompts";import L from"picocolors";import{Command as ps}from"commander";import Fn from"fs";import Jt from"path";import{fileURLToPath as as}from"url";function cs(){try{let t=Jt.dirname(as(import.meta.url));for(let n=0;n<4;n++){let o=Jt.join(t,"package.json");if(Fn.existsSync(o)){let r=Fn.readFileSync(o,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=Jt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var z=cs();var ls="create-sailor";function jn(){let e=new ps;return e.name(ls).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(z,"-v, --version").helpOption(!1).argument("[name]","project name or path (default: my-app; use . for current 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 Vn from"picocolors";var Qt=[{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 mt(e){return Qt.find(t=>t.id===e)}function Bn(e){return e==="cn"||e==="hybrid"?"local":"supabase"}var Re=[{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 Zt(e){let t=e==="supabase"?"supabase-storage":e;return Re.some(n=>n.id===t)?t:void 0}function $n(e){let t=Zt(e);return t?Re.find(n=>n.id===t):void 0}var Ap=Re.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Yn(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function en(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 tn(e,t,n){let o=e?.trim().toLowerCase()??Bn(t),r=mt(o);if(!r){let i=Qt.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 nn(e){return e==="drizzle"?"drizzle":"prisma"}function gt(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function ft(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 on(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 ds=new Set(["gateway","direct","custom","none"]);function rn(e){if(!e)return!1;let t=e.trim().toLowerCase();return ds.has(t)}function sn(e){if(!e)return["openai"];if(rn(e))return[];let t=e.split(",").map(n=>n.trim().toLowerCase());return t.includes("none")?[]:t}function qn(e,t){let n=e??t;return Zt(n)??n}var Kn={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function an(e,t){if(!e)return"fumadocs";let n=e.toLowerCase();if(n==="fumadocs"||n==="none")return n;if(n in Kn){let o=Kn[n];return t?process.stdout.write(JSON.stringify({event:"notice",kind:"docs-fallback",requested:n,effective:"fumadocs"})+`
3
+ `):process.stdout.write(Vn.yellow(`\u26A0 ${o} support is coming in v1.2. Falling back to fumadocs.
4
+ `)+Vn.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
5
+ `)),"fumadocs"}return"fumadocs"}function yt(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 cn(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function Gn(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 pn(e){return e==="cn"?"wechat":"stripe"}import*as q from"@clack/prompts";import Ts from"picocolors";var ln=[{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:[]}],kp=ln.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var us=["openai","anthropic","google"],ms=["openai"];function dn(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let n=t.length>0?t:[...us];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:[...ms];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 Ze=[{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"}],gs=new Set(Ze.map(e=>e.id));function Hn(e){return Ze.find(t=>t.id===e)}function Wn(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)gs.has(r)&&!o.has(r)&&(n.push(r),o.add(r));return n}import te from"fs";import T from"path";import{fileURLToPath as bs}from"url";var Xn=["web","landing","auth","admin","design-docs","sailor-docs","router","forge","typelens","gateway","python-ai"],fs={web:"frontend",landing:"frontend",auth:"frontend",admin:"frontend","design-docs":"frontend","sailor-docs":"frontend",router:"frontend",forge:"frontend",typelens:"frontend",gateway:"edgeGateway","python-ai":"originBackend"},ys={frontend:"vercel",edgeGateway:"cloudflare-workers",originBackend:"ecs-docker"};function Ss(e){return Xn.includes(e)}function hs(e){if(!Ss(e))throw new Error(`Unknown deploy service '${e}'. Deploy targets apply only to apps/backends, not packages.`)}function Es(e){return hs(e),fs[e]}function vs(e){let t=Es(e);return ys[t]}function zn(){return Object.fromEntries(Xn.map(e=>[e,vs(e)]))}var _s=bs(import.meta.url),Jn=T.dirname(_s),ws="cloudflare-pages",Ps="standalone",As="railway";function un(e,t,n,o){return{...e,web:t,landing:t,auth:t,admin:t,"design-docs":t,"sailor-docs":t,router:t,forge:t,typelens:t,gateway:n,"python-ai":o}}function Cs(){let e=[T.join(Jn,"..","templates","deploy"),T.join(Jn,"..","..","templates","deploy")];for(let t of e)if(te.existsSync(t))return t;return e[0]}function Ct(e){let t=zn();switch(e){case"cloudflare":return un(t,ws,"cloudflare-workers","ecs-docker");case"selfhost":return un(t,Ps,"ecs-docker","ecs-docker");case"railway":return un(t,As,"railway","railway");case"none":case"vercel":return t}}function Is(e){return`DEPLOY_TARGET_${e.toUpperCase().replace(/-/g,"_")}`}async function Qn(e,t){let n=T.join(e,"backends","gateway");te.existsSync(n)&&await te.promises.copyFile(T.join(t,"wrangler.gateway.toml"),T.join(n,"wrangler.toml"))}async function Zn(e,t){let n=T.join(e,".env.example"),o;try{o=await te.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])=>`${Is(i)}="${a}"`)].join(`
6
6
  `);await te.promises.appendFile(n,`${s}
7
- `)}async function to(e,t){if(t==="none")return;let n=Cs();t==="vercel"?(await te.promises.copyFile(T.join(n,"vercel.json"),T.join(e,"vercel.json")),await Zn(e,n)):t==="railway"?await te.promises.copyFile(T.join(n,"railway.toml"),T.join(e,"railway.toml")):t==="cloudflare"?(await te.promises.copyFile(T.join(n,"wrangler.toml"),T.join(e,"wrangler.toml")),await Zn(e,n)):t==="selfhost"&&(await te.promises.copyFile(T.join(n,"docker-compose.yml"),T.join(e,"docker-compose.yml")),await te.promises.copyFile(T.join(n,"Dockerfile.web"),T.join(e,"Dockerfile.web")))}var xs={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 Rs(e){return e?xs[e]??"stable":"stable"}function et(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function Te(e){switch(e){case"stable":return"Production-ready.";case"foundation":return"Foundation status \u2014 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 It(e){let t=[];for(let{flag:n,provider:o}of e){if(!o||o==="none")continue;let r=Rs(o);r!=="stable"&&t.push({flag:n,provider:o,status:r})}return t}function _e(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 no(e,t){let n=t==="cn";return{cronJobs:_e(e.cronJobs,!0),auditLog:_e(e.auditLog,!1),apiKeys:_e(e.apiKeys,!0),webhooks:_e(e.webhooks,!0),commandPalette:_e(e.commandPalette,!0),cookieConsent:_e(e.cookieConsent,!0),legalPages:_e(e.legalPages,!0),chinaCompliance:_e(e.chinaCompliance,n)}}async function ks(e,t,n,o){let r={};return t||(r.region=()=>q.select({message:"Target region?",options:[{value:"global",label:"Global",hint:"Stripe \xB7 Resend \xB7 R2 defaults"},{value:"cn",label:"China",hint:"WeChat Pay \xB7 Aliyun DM/OSS defaults"},{value:"hybrid",label:"Hybrid",hint:"global + CN dual track"}],initialValue:"global"})),n||(r.auth=()=>q.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=()=>q.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=ln.map(a=>({value:a.id,label:`[${a.category}] ${a.name}`}));return q.multiselect({message:"Select direct AI provider adapters (expert path)",options:i,initialValues:["openai"],required:!1})},r.customAiName=({results:s})=>s.aiMode==="custom"?q.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),r.customAiBaseUrl=({results:s})=>s.aiMode==="custom"?q.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"?q.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 q.group(r,{onCancel:()=>{process.stdout.write(Ts.red(`\u2718 Cancelled
8
- `)),process.exit(130)}})}async function oo(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,d=!!e.sms,u=e.i18n!==void 0,h=!!e.yes||!process.stdin.isTTY,g,E,S,m,_,H,M,he=Xn(e.socialLogin),le,ee,$,K,C,W,de;if(h){g=cn(e.region),E=nn(e.orm);{let Y=en(e.db),At=tn(e.dbHost,g,Y);S=At.engine,m=At.hostId}let X=r?e.payment:pn(g);_=gt(X),H=ft(X),M=on(e.auth);let Qe="gateway";if(s){let Y=e.ai?.trim().toLowerCase()??"";rn(Y)?Qe=Y:Qe="direct"}let ut=dn({mode:Qe,providerIds:s?sn(e.ai):void 0});le=ut.mode,ee=ut.routing,$=ut.providerIds,C=yt(e.deploy),W=an(e.docs,t),de=u?!!e.i18n:!0}else{let X=await ks(e,n,o,s);g=cn(n?e.region:X.region),E=nn(e.orm);{let At=en(e.db),Mn=tn(e.dbHost,g,At);S=Mn.engine,m=Mn.hostId}let Qe=r?e.payment:pn(g);_=gt(Qe),H=ft(Qe),M=on(o?e.auth:X.auth);let ut=X.aiMode==="custom"?{name:X.customAiName??"custom",baseURL:X.customAiBaseUrl??"",apiKeyEnvName:X.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,Y=dn({mode:s?e.ai?.trim().toLowerCase()==="none"?"none":"direct":X.aiMode??"gateway",providerIds:s?sn(e.ai):X.aiProviders,customEndpoint:ut});le=Y.mode,ee=Y.routing,$=Y.providerIds,Y.customEndpoint&&(K={name:Y.customEndpoint.name,baseURL:Y.customEndpoint.baseURL,apiKeyEnvName:Y.customEndpoint.apiKeyEnvName}),C=yt(e.deploy),W=an(e.docs,t),de=u?!!e.i18n:!0}let P=Hn(g),Ee=i?e.email:P.email,ze=Gn(a?e.storage:void 0,P.storage),Je=c?e.monitoring:P.monitoring,ve=p?e.analytics:P.analytics,v=d?e.sms:P.sms,R=e.queue??P.queue,w=e.search??P.search,I=e.cache??P.cache,Gt=e.notifications??P.notifications,Ht=e.webhooks??P.webhooks,kn=e.cms??P.cms,Wt=e.featureFlags??P.featureFlags,Xt=e.captcha??P.captcha,Nn=e.mcp??P.mcp,On=e.metering??P.metering,Ln=e.billingMode??P.billingMode,Un=e.idp??P.idp,zt=e.accessGate==="invite"?"invite":P.accessGate,Dn=Ct(C),be=no({cronJobs:e.cronJobs,auditLog:e.auditLog,apiKeys:e.apiKeys,commandPalette:e.commandPalette,cookieConsent:e.cookieConsent,legalPages:e.legalPages,chinaCompliance:e.chinaCompliance},g),ss=It([{flag:"queue",provider:R},{flag:"search",provider:w},{flag:"notifications",provider:Gt},{flag:"webhooks",provider:Ht},{flag:"feature-flags",provider:Wt},{flag:"captcha",provider:Xt},{flag:"access-gate",provider:zt}]),is={region:g,orm:E,database:S,databaseHost:m,payment:_,aiMode:le,aiRouting:ee,aiProviders:$,customAiEndpoint:K,deployTarget:C,deployTargets:Dn,docs:W,i18n:de,email:Ee,storage:ze,monitoring:Je,analytics:ve,sms:v,queue:R,search:w,cache:I,notifications:Gt,webhooks:Ht,cms:kn,featureFlags:Wt,captcha:Xt,mcp:Nn,metering:On,billingMode:Ln,idp:Un,accessGate:zt,cronJobs:be.cronJobs,auditLog:be.auditLog,apiKeys:be.apiKeys,commandPalette:be.commandPalette,cookieConsent:be.cookieConsent,legalPages:be.legalPages,chinaCompliance:be.chinaCompliance};return{region:g,orm:E,database:S,databaseHost:m,payment:_,paymentChoice:H,auth:M,socialLoginIds:he,aiMode:le,aiRouting:ee,aiProviders:$,customAiEndpoint:K,deployTarget:C,deployTargets:Dn,docs:W,i18n:de,email:Ee,storage:ze,monitoring:Je,analytics:ve,sms:v,queue:R,search:w,cache:I,notifications:Gt,webhooks:Ht,cms:kn,featureFlags:Wt,captcha:Xt,mcp:Nn,metering:On,billingMode:Ln,idp:Un,accessGate:zt,waveToggles:be,previewSelections:ss,config:is}}import{execFileSync as Kt}from"child_process";import Yt from"fs";import Xe from"path";import We from"picocolors";import Xc from"update-notifier";import tt from"picocolors";function Ns(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function ro(e){let t=Ns(),n=t?"\u2693":"-",o=t?"\u25B8":"->",r=e.packageManager??"pnpm",s=e.hasDatabase!==!1,i=e.targetDir==="."||e.targetDir==="./"||e.targetDir===".\\",a=i?".":e.targetDir.endsWith("/")?e.targetDir:`${e.targetDir}/`,c=t?tt.bold(`${n} Done in ${e.elapsedSec}s \xB7 ${a}`):`${n} Done in ${e.elapsedSec}s \xB7 ${a}`,p=h=>t?tt.dim(h):h,d=h=>t?tt.bold(h):h,u=["",` ${c}`,"",` ${d("Next:")}`];i||u.push(` ${o} cd ${e.targetDir}`),e.skippedInstall&&u.push(` ${o} ${r} install`),u.push(` ${o} fill .env.local ${p("\u2192 provider keys from .env.example")}`),s&&u.push(` ${o} ${r} infra:up ${p("\u2192 local Postgres (optional)")}`,` ${o} ${r} db:migrate ${p("\u2192 apply Prisma schema")}`),u.push(` ${o} ${r} dev ${p("\u2192 http://localhost:3000")}`,"",` ${p("More:")} ${p("nebutra doctor")} ${p("\xB7")} ${p("docs.nebutra.com")}`);let A=e.previewSelections??[];if(A.length>0){let h=t?tt.bold(tt.yellow("\u26A0 Preview / foundation providers:")):"!! Preview / foundation providers:";u.push("",` ${h}`);for(let g of A){let E=et(g.status),S=` ${o} ${g.flag}=${g.provider} ${E}`;u.push(t?tt.yellow(S):S)}u.push(` ${p(Te("foundation"))}`)}u.push(""),process.stdout.write(u.join(`
7
+ `)}async function eo(e,t){if(t==="none")return;let n=Cs();t==="vercel"?(await te.promises.copyFile(T.join(n,"vercel.json"),T.join(e,"vercel.json")),await Qn(e,n)):t==="railway"?await te.promises.copyFile(T.join(n,"railway.toml"),T.join(e,"railway.toml")):t==="cloudflare"?(await te.promises.copyFile(T.join(n,"wrangler.toml"),T.join(e,"wrangler.toml")),await Qn(e,n)):t==="selfhost"&&(await te.promises.copyFile(T.join(n,"docker-compose.yml"),T.join(e,"docker-compose.yml")),await te.promises.copyFile(T.join(n,"Dockerfile.web"),T.join(e,"Dockerfile.web")))}var xs={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 Rs(e){return e?xs[e]??"stable":"stable"}function et(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function Te(e){switch(e){case"stable":return"Production-ready.";case"foundation":return"Foundation status \u2014 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 It(e){let t=[];for(let{flag:n,provider:o}of e){if(!o||o==="none")continue;let r=Rs(o);r!=="stable"&&t.push({flag:n,provider:o,status:r})}return t}function _e(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 to(e,t){let n=t==="cn";return{cronJobs:_e(e.cronJobs,!0),auditLog:_e(e.auditLog,!1),apiKeys:_e(e.apiKeys,!0),webhooks:_e(e.webhooks,!0),commandPalette:_e(e.commandPalette,!0),cookieConsent:_e(e.cookieConsent,!0),legalPages:_e(e.legalPages,!0),chinaCompliance:_e(e.chinaCompliance,n)}}async function ks(e,t,n,o){let r={};return t||(r.region=()=>q.select({message:"Target region?",options:[{value:"global",label:"Global",hint:"Stripe \xB7 Resend \xB7 R2 defaults"},{value:"cn",label:"China",hint:"WeChat Pay \xB7 Aliyun DM/OSS defaults"},{value:"hybrid",label:"Hybrid",hint:"global + CN dual track"}],initialValue:"global"})),n||(r.auth=()=>q.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=()=>q.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=ln.map(a=>({value:a.id,label:`[${a.category}] ${a.name}`}));return q.multiselect({message:"Select direct AI provider adapters (expert path)",options:i,initialValues:["openai"],required:!1})},r.customAiName=({results:s})=>s.aiMode==="custom"?q.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),r.customAiBaseUrl=({results:s})=>s.aiMode==="custom"?q.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"?q.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 q.group(r,{onCancel:()=>{process.stdout.write(Ts.red(`\u2718 Cancelled
8
+ `)),process.exit(130)}})}async function no(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,d=!!e.sms,u=e.i18n!==void 0,h=!!e.yes||!process.stdin.isTTY,g,E,S,m,_,H,M,he=Wn(e.socialLogin),le,ee,V,K,C,W,de;if(h){g=cn(e.region),E=nn(e.orm);{let Y=en(e.db),At=tn(e.dbHost,g,Y);S=At.engine,m=At.hostId}let X=r?e.payment:pn(g);_=gt(X),H=ft(X),M=on(e.auth);let Qe="gateway";if(s){let Y=e.ai?.trim().toLowerCase()??"";rn(Y)?Qe=Y:Qe="direct"}let ut=dn({mode:Qe,providerIds:s?sn(e.ai):void 0});le=ut.mode,ee=ut.routing,V=ut.providerIds,C=yt(e.deploy),W=an(e.docs,t),de=u?!!e.i18n:!0}else{let X=await ks(e,n,o,s);g=cn(n?e.region:X.region),E=nn(e.orm);{let At=en(e.db),Mn=tn(e.dbHost,g,At);S=Mn.engine,m=Mn.hostId}let Qe=r?e.payment:pn(g);_=gt(Qe),H=ft(Qe),M=on(o?e.auth:X.auth);let ut=X.aiMode==="custom"?{name:X.customAiName??"custom",baseURL:X.customAiBaseUrl??"",apiKeyEnvName:X.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,Y=dn({mode:s?e.ai?.trim().toLowerCase()==="none"?"none":"direct":X.aiMode??"gateway",providerIds:s?sn(e.ai):X.aiProviders,customEndpoint:ut});le=Y.mode,ee=Y.routing,V=Y.providerIds,Y.customEndpoint&&(K={name:Y.customEndpoint.name,baseURL:Y.customEndpoint.baseURL,apiKeyEnvName:Y.customEndpoint.apiKeyEnvName}),C=yt(e.deploy),W=an(e.docs,t),de=u?!!e.i18n:!0}let w=Gn(g),Ee=i?e.email:w.email,ze=qn(a?e.storage:void 0,w.storage),Je=c?e.monitoring:w.monitoring,ve=p?e.analytics:w.analytics,v=d?e.sms:w.sms,R=e.queue??w.queue,P=e.search??w.search,I=e.cache??w.cache,Gt=e.notifications??w.notifications,Ht=e.webhooks??w.webhooks,kn=e.cms??w.cms,Wt=e.featureFlags??w.featureFlags,Xt=e.captcha??w.captcha,Nn=e.mcp??w.mcp,On=e.metering??w.metering,Ln=e.billingMode??w.billingMode,Un=e.idp??w.idp,zt=e.accessGate==="invite"?"invite":w.accessGate,Dn=Ct(C),be=to({cronJobs:e.cronJobs,auditLog:e.auditLog,apiKeys:e.apiKeys,commandPalette:e.commandPalette,cookieConsent:e.cookieConsent,legalPages:e.legalPages,chinaCompliance:e.chinaCompliance},g),ss=It([{flag:"queue",provider:R},{flag:"search",provider:P},{flag:"notifications",provider:Gt},{flag:"webhooks",provider:Ht},{flag:"feature-flags",provider:Wt},{flag:"captcha",provider:Xt},{flag:"access-gate",provider:zt}]),is={region:g,orm:E,database:S,databaseHost:m,payment:_,aiMode:le,aiRouting:ee,aiProviders:V,customAiEndpoint:K,deployTarget:C,deployTargets:Dn,docs:W,i18n:de,email:Ee,storage:ze,monitoring:Je,analytics:ve,sms:v,queue:R,search:P,cache:I,notifications:Gt,webhooks:Ht,cms:kn,featureFlags:Wt,captcha:Xt,mcp:Nn,metering:On,billingMode:Ln,idp:Un,accessGate:zt,cronJobs:be.cronJobs,auditLog:be.auditLog,apiKeys:be.apiKeys,commandPalette:be.commandPalette,cookieConsent:be.cookieConsent,legalPages:be.legalPages,chinaCompliance:be.chinaCompliance};return{region:g,orm:E,database:S,databaseHost:m,payment:_,paymentChoice:H,auth:M,socialLoginIds:he,aiMode:le,aiRouting:ee,aiProviders:V,customAiEndpoint:K,deployTarget:C,deployTargets:Dn,docs:W,i18n:de,email:Ee,storage:ze,monitoring:Je,analytics:ve,sms:v,queue:R,search:P,cache:I,notifications:Gt,webhooks:Ht,cms:kn,featureFlags:Wt,captcha:Xt,mcp:Nn,metering:On,billingMode:Ln,idp:Un,accessGate:zt,waveToggles:be,previewSelections:ss,config:is}}import{execFileSync as Kt}from"child_process";import Yt from"fs";import Xe from"path";import We from"picocolors";import zc from"update-notifier";import tt from"picocolors";function Ns(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function oo(e){let t=Ns(),n=t?"\u2693":"-",o=t?"\u25B8":"->",r=e.packageManager??"pnpm",s=e.hasDatabase!==!1,i=e.targetDir==="."||e.targetDir==="./"||e.targetDir===".\\",a=i?".":e.targetDir.endsWith("/")?e.targetDir:`${e.targetDir}/`,c=t?tt.bold(`${n} Done in ${e.elapsedSec}s \xB7 ${a}`):`${n} Done in ${e.elapsedSec}s \xB7 ${a}`,p=h=>t?tt.dim(h):h,d=h=>t?tt.bold(h):h,u=["",` ${c}`,"",` ${d("Next:")}`];i||u.push(` ${o} cd ${e.targetDir}`),e.skippedInstall&&u.push(` ${o} ${r} install`),u.push(` ${o} fill .env.local ${p("\u2192 provider keys from .env.example")}`),s&&u.push(` ${o} ${r} infra:up ${p("\u2192 local Postgres (optional)")}`,` ${o} ${r} db:migrate ${p("\u2192 apply Prisma schema")}`),u.push(` ${o} ${r} dev ${p("\u2192 http://localhost:3000")}`,"",` ${p("More:")} ${p("nebutra doctor")} ${p("\xB7")} ${p("docs.nebutra.com")}`);let A=e.previewSelections??[];if(A.length>0){let h=t?tt.bold(tt.yellow("\u26A0 Preview / foundation providers:")):"!! Preview / foundation providers:";u.push("",` ${h}`);for(let g of A){let E=et(g.status),S=` ${o} ${g.flag}=${g.provider} ${E}`;u.push(t?tt.yellow(S):S)}u.push(` ${p(Te("foundation"))}`)}u.push(""),process.stdout.write(u.join(`
9
9
  `)+`
10
- `)}import nt from"fs";import B from"path";var so=[{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:""}],tl=so.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function io(e){return so.find(t=>t.id===e)}function Os(e){nt.mkdirSync(e,{recursive:!0})}function ne(e,t){Os(B.dirname(e)),nt.writeFileSync(e,t)}function ke(e,t){let n=B.join(e,".env.example");nt.existsSync(n)?nt.appendFileSync(n,`
10
+ `)}import nt from"fs";import B from"path";var ro=[{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:""}],nl=ro.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function so(e){return ro.find(t=>t.id===e)}function Os(e){nt.mkdirSync(e,{recursive:!0})}function ne(e,t){Os(B.dirname(e)),nt.writeFileSync(e,t)}function ke(e,t){let n=B.join(e,".env.example");nt.existsSync(n)?nt.appendFileSync(n,`
11
11
  `+t):nt.writeFileSync(n,t)}function Ls(e){let t=`"use client";
12
12
  /**
13
13
  * PostHog browser SDK \u2014 lazy-initialized on first access.
@@ -181,10 +181,10 @@ export function trackServer(
181
181
  if (!c) return;
182
182
  c.track(event, { distinct_id: distinctId, ...properties });
183
183
  }
184
- `;ne(B.join(e,"src","lib","analytics","mixpanel.client.ts"),t),ne(B.join(e,"src","lib","analytics","mixpanel.server.ts"),n)}function Vs(){return`# Mixpanel \u2014 product analytics
184
+ `;ne(B.join(e,"src","lib","analytics","mixpanel.client.ts"),t),ne(B.join(e,"src","lib","analytics","mixpanel.server.ts"),n)}function $s(){return`# Mixpanel \u2014 product analytics
185
185
  MIXPANEL_TOKEN=
186
186
  NEXT_PUBLIC_MIXPANEL_TOKEN=
187
- `}function $s(e){ne(B.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
187
+ `}function Vs(e){ne(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
  */
@@ -270,19 +270,19 @@ gdp("send");
270
270
  }
271
271
  `)}function Hs(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
272
272
  NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID=
273
- `}async function ao(e,t,n="global"){let o=io(t);if(!o||o.id==="none")return;let r=B.join(e,"apps","web");if(!nt.existsSync(r))return;let s=o.id;try{switch(s){case"posthog":Ls(r),ke(e,Us());return;case"plausible":Ds(r),ke(e,Ms());return;case"umami":Fs(r),ke(e,js());return;case"mixpanel":Bs(r),ke(e,Vs());return;case"baidu":$s(r),ke(e,Ks());return;case"sensors":Ys(r),ke(e,qs());return;case"growingio":Gs(r),ke(e,Hs());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=Fn("analytics");function Xs(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function co(e,t={}){Xs(t)||(async()=>{try{let n=await import("./dist-ZZCU5PKC.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 G from"fs";import k from"path";function V(e){G.existsSync(e)&&G.rmSync(e,{recursive:!0,force:!0})}function xt(e,t){let n=k.join(e,".env.example");G.existsSync(n)?G.appendFileSync(n,`
274
- `+t):G.writeFileSync(n,t)}function Rt(e,t){if(!G.existsSync(e))return;let n=G.readFileSync(e,"utf8"),o=n.replace(/export type AuthProviderId\s*=\s*(?:"[^"]+"\s*\|\s*)+"[^"]+";/,`export type AuthProviderId = "${t}";`);o!==n&&G.writeFileSync(e,o)}function zs(e,t){let n=k.join(e,"README.md");if(!G.existsSync(n)){G.writeFileSync(n,t);return}G.appendFileSync(n,`
275
- `+t)}async function po(e,t){let n=k.join(e,"packages","iam","auth");if(!G.existsSync(n))return;if(t==="none"){V(n),zs(e,`
273
+ `}async function io(e,t,n="global"){let o=so(t);if(!o||o.id==="none")return;let r=B.join(e,"apps","web");if(!nt.existsSync(r))return;let s=o.id;try{switch(s){case"posthog":Ls(r),ke(e,Us());return;case"plausible":Ds(r),ke(e,Ms());return;case"umami":Fs(r),ke(e,js());return;case"mixpanel":Bs(r),ke(e,$s());return;case"baidu":Vs(r),ke(e,Ks());return;case"sensors":Ys(r),ke(e,qs());return;case"growingio":Gs(r),ke(e,Hs());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={name:"Nebutra",nameCn:"\u4E91\u6BD3\u667A\u80FD",nameFull:"\u65E0\u9521\u4E91\u6BD3\u667A\u80FD\u79D1\u6280\u6709\u9650\u516C\u53F8",nameFullEn:"Wuxi Nebutra Intelligence Technology Co., Ltd.",tagline:"Ship AI products, not boilerplate.",taglineCn:"AI\u539F\u751F\xB7\u5FEB\u901F\u51FA\u6D77\xB7\u5373\u523B\u4EA4\u4ED8",description:"Production-ready Next.js monorepo template for AI SaaS products. Auth, billing, multi-tenancy, AI services, design system, and enterprise infrastructure \u2014 pre-configured.",descriptionCn:"\u9762\u5411AI\u521B\u4E1A\u8005\u7684\u4E00\u4F53\u5316SaaS\u57FA\u7840\u8BBE\u65BD\u6A21\u677F\uFF0C\u8986\u76D6\u8BA4\u8BC1\u3001\u8BA1\u8D39\u3001\u591A\u79DF\u6237\u3001AI\u670D\u52A1\u4E0E\u8BBE\u8BA1\u7CFB\u7EDF\uFF0C\u5F00\u7BB1\u5373\u4EA7\u54C1",story:{concept:"Logo\u4EE5\u9996\u5B57\u6BCDN\u7684\u57FA\u7840\u9020\u578B\u6982\u5FF5\u4E3A\u4E3B\u8981\u8BBE\u8BA1\u6846\u67B6\uFF0C\u901A\u8FC7\u51E0\u4F55\u6B63\u8D1F\u7A7A\u95F4\u6784\u5EFA\u9690\u5F62'N'\uFF0C\u5F62\u6210\u8FD1\u4F3C\u516D\u8FB9\u5F62\u7684\u7A33\u5B9A\u7ED3\u6784",colorMeaning:"\u84DD\u7EFF\u6E10\u53D8\u4F53\u73B0\u672A\u6765\u611F\u4E0E\u79D1\u6280\u950B\u8292\uFF0C'\u4E91'\u4EE3\u8868\u4E91\u7AEF\u5E73\u53F0\uFF0C'\u6BD3'\u5BD3\u610F\u5B55\u80B2\u4E0E\u8F6C\u5316",values:["AI Native","Ship Fast","Open by Default","Global-Ready","Enterprise-Grade"],missionStatement:"Help AI founders and SaaS teams go from idea to production 10x faster by providing the infrastructure layer they shouldn't have to build."},domains:{landing:"nebutra.com",app:"app.nebutra.com",api:"api.nebutra.com",auth:"auth.nebutra.com",sso:"sso.nebutra.com",docs:"docs.nebutra.com",studio:"studio.nebutra.com",cdn:"cdn.nebutra.com",router:"router.nebutra.com",forge:"forge.nebutra.com",design:"design.nebutra.com",status:"status.nebutra.com",admin:"admin.nebutra.com",analytics:"analytics.nebutra.com",pebble:"pebble.nebutra.com",carina:"carina.nebutra.com",origin:"origin.nebutra.com"},social:{twitter:"https://twitter.com/nebutra",github:"https://github.com/nebutra",discord:"https://discord.gg/nebutra",linkedin:"https://linkedin.com/company/nebutra"}};function ao(e){let t=Ws.domains[e];if(!t?.trim())throw new Error(`brand.domains.${String(e)} is empty \u2014 run brand:apply`);return`https://${t.replace(/^https?:\/\//,"").replace(/\/+$/,"")}`}var Xs=ao("analytics");function zs(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function co(e,t={}){zs(t)||(async()=>{try{let n=await import("@nebutra/analytics");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??Xs},onError:()=>{}});if(typeof o?.track!="function")return;let r=o.track("scaffold.completed",e);r&&typeof r.then=="function"&&await r.catch(()=>{})}catch{}})()}import G from"fs";import k from"path";function $(e){G.existsSync(e)&&G.rmSync(e,{recursive:!0,force:!0})}function xt(e,t){let n=k.join(e,".env.example");G.existsSync(n)?G.appendFileSync(n,`
274
+ `+t):G.writeFileSync(n,t)}function Rt(e,t){if(!G.existsSync(e))return;let n=G.readFileSync(e,"utf8"),o=n.replace(/export type AuthProviderId\s*=\s*(?:"[^"]+"\s*\|\s*)+"[^"]+";/,`export type AuthProviderId = "${t}";`);o!==n&&G.writeFileSync(e,o)}function Js(e,t){let n=k.join(e,"README.md");if(!G.existsSync(n)){G.writeFileSync(n,t);return}G.appendFileSync(n,`
275
+ `+t)}async function po(e,t){let n=k.join(e,"packages","iam","auth");if(!G.existsSync(n))return;if(t==="none"){$(n),Js(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=k.join(n,"src","providers"),r=k.join(n,"src","types.ts");if(t==="clerk"){V(k.join(o,"better-auth.ts")),V(k.join(o,"nextauth.ts")),V(k.join(o,"supabase.ts")),Rt(r,"clerk"),xt(e,`# Clerk auth
279
+ `);return}let o=k.join(n,"src","providers"),r=k.join(n,"src","types.ts");if(t==="clerk"){$(k.join(o,"better-auth.ts")),$(k.join(o,"nextauth.ts")),$(k.join(o,"supabase.ts")),Rt(r,"clerk"),xt(e,`# Clerk auth
280
280
  CLERK_PUBLISHABLE_KEY=
281
281
  CLERK_SECRET_KEY=
282
- `);return}if(t==="betterauth"){V(k.join(o,"clerk.ts")),V(k.join(o,"nextauth.ts")),V(k.join(o,"supabase.ts")),Rt(r,"better-auth"),xt(e,`# Better Auth
282
+ `);return}if(t==="betterauth"){$(k.join(o,"clerk.ts")),$(k.join(o,"nextauth.ts")),$(k.join(o,"supabase.ts")),Rt(r,"better-auth"),xt(e,`# Better Auth
283
283
  BETTER_AUTH_SECRET=
284
284
  BETTER_AUTH_URL=http://localhost:3000
285
- `);return}if(t==="nextauth"){V(k.join(o,"clerk.ts")),V(k.join(o,"better-auth.ts")),V(k.join(o,"supabase.ts")),Rt(r,"nextauth"),xt(e,`# NextAuth (Auth.js v5)
285
+ `);return}if(t==="nextauth"){$(k.join(o,"clerk.ts")),$(k.join(o,"better-auth.ts")),$(k.join(o,"supabase.ts")),Rt(r,"nextauth"),xt(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(k.join(o,"clerk.ts")),V(k.join(o,"better-auth.ts")),V(k.join(o,"nextauth.ts")),Rt(r,"supabase"),xt(e,`# Supabase Auth
293
+ `);return}if(t==="supabase"){$(k.join(o,"clerk.ts")),$(k.join(o,"better-auth.ts")),$(k.join(o,"nextauth.ts")),Rt(r,"supabase"),xt(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 Oe from"fs";import Ne from"path";function Js(e,t){let n=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
301
+ `);return}}import Oe from"fs";import Ne from"path";function Qs(e,t){let n=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
302
302
  // Generated by create-sailor \u2014 OAuth callback for ${e.name}
303
303
  // Primary auth provider: ${t}
304
304
  // Docs: ${e.docs}`,o={wechat:` const tokenRes = await fetch(
@@ -423,7 +423,7 @@ ${o[e.id]}
423
423
  void state;
424
424
  return NextResponse.redirect(new URL("/dashboard", req.url));
425
425
  }
426
- `}function Qs(e){return`"use client";
426
+ `}function Zs(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 lo(e){Oe.mkdirSync(e,{recursive:!0})}function Zs(e,t){let n=Ne.join(e,".env.example");Oe.existsSync(n)?Oe.appendFileSync(n,`
470
- `+t):Oe.writeFileSync(n,t)}function ei(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,n=e.envVars.map(o=>`${o}=`).join(`
469
+ `}function lo(e){Oe.mkdirSync(e,{recursive:!0})}function ei(e,t){let n=Ne.join(e,".env.example");Oe.existsSync(n)?Oe.appendFileSync(n,`
470
+ `+t):Oe.writeFileSync(n,t)}function ti(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 uo(e,t,n){if(!t||t.length===0)return;let o=Ne.join(e,"apps","web");if(!Oe.existsSync(o))return;let r=new Set,s=[];for(let p of t){if(r.has(p))continue;r.add(p);let d=Wn(p);d&&s.push(d)}if(s.length===0)return;for(let p of s)Zs(e,ei(p));let i=Ne.join(o,"src","app","api","auth","callback");for(let p of s){let d=Ne.join(i,p.id);lo(d);let u=Ne.join(d,"route.ts");Oe.writeFileSync(u,Js(p,n))}let a=Ne.join(o,"src","components","auth");lo(a);let c=Ne.join(a,"SocialLoginButtons.tsx");Oe.writeFileSync(c,Qs(s))}import ot from"fs";import go from"path";var Tt=[{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 mo(e){return Tt.find(t=>t.id===e)}var yl=Tt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import oe from"fs";import kt from"path";function re(e,t){let n=kt.join(e,".env.example");if(!oe.existsSync(n)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(oe.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(`
473
+ `}async function uo(e,t,n){if(!t||t.length===0)return;let o=Ne.join(e,"apps","web");if(!Oe.existsSync(o))return;let r=new Set,s=[];for(let p of t){if(r.has(p))continue;r.add(p);let d=Hn(p);d&&s.push(d)}if(s.length===0)return;for(let p of s)ei(e,ti(p));let i=Ne.join(o,"src","app","api","auth","callback");for(let p of s){let d=Ne.join(i,p.id);lo(d);let u=Ne.join(d,"route.ts");Oe.writeFileSync(u,Qs(p,n))}let a=Ne.join(o,"src","components","auth");lo(a);let c=Ne.join(a,"SocialLoginButtons.tsx");Oe.writeFileSync(c,Zs(s))}import ot from"fs";import go from"path";var Tt=[{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 mo(e){return Tt.find(t=>t.id===e)}var hl=Tt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import oe from"fs";import kt from"path";function re(e,t){let n=kt.join(e,".env.example");if(!oe.existsSync(n)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(oe.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
474
  `);oe.appendFileSync(n,a)}function se(e,t,n){let o=kt.join(e,".env.example");if(!oe.existsSync(o))return;let r=oe.readFileSync(o,"utf-8"),s=`${t}="${n}"`,i=new RegExp(`^${t}=.*$`,"m");if(i.test(r)){oe.writeFileSync(o,r.replace(i,s));return}let a=r.endsWith(`
475
475
  `)?"":`
476
476
  `;oe.appendFileSync(o,`${a}${s}
477
- `)}var ti=["design","iam","commerce","integrations","platform","ops","ai"];function Le(e,t){for(let o of ti){let r=kt.join(e,"packages",o,t);if(oe.existsSync(r))return r}let n=kt.join(e,"packages",t);return oe.existsSync(n)?n:null}function J(e,t){let n=Le(e,t);n&&oe.rmSync(n,{recursive:!0,force:!0})}function fo(e){return ot.existsSync(e)?ot.readFileSync(e,"utf-8"):null}function ni(e,t){let n=go.join(e,".env.example"),o=fo(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
- `);ot.appendFileSync(n,s)}function oi(e,t,n){let o=go.join(e,".env.example"),r=fo(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?ot.writeFileSync(o,r.replace(s,`${t}="${n}"`)):ot.appendFileSync(o,`${t}="${n}"
479
- `)}async function yo(e,t,n){let o=Le(e,"cache");if(t==="none"){o&&ot.rmSync(o,{recursive:!0,force:!0});return}let r=mo(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${Tt.map(s=>s.id).join(", ")}`);o&&(ni(e,r),oi(e,"CACHE_PROVIDER",t))}var Nt=[{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 So(e){return Nt.find(t=>t.id===e)}var Cl=Nt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function ho(e,t,n="global"){let o=So(t);if(!o)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${Nt.map(r=>r.id).join(", ")}`);if(o.id==="none"){J(e,"captcha");return}o.envVars.length>0&&re(e,{category:"Captcha",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"CAPTCHA_PROVIDER",o.id)}import Lt from"fs";import ri from"path";var Ot=[{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 Eo(e){return Ot.find(t=>t.id===e)}var kl=Ot.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function vo(e,t,n="global"){let o=Eo(t);if(!o)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${Ot.map(s=>s.id).join(", ")}`);let r=ri.join(e,"apps","studio");if(o.id==="none"){J(e,"sanity"),Lt.existsSync(r)&&Lt.rmSync(r,{recursive:!0,force:!0});return}o.id!=="sanity"&&(J(e,"sanity"),Lt.existsSync(r)&&Lt.rmSync(r,{recursive:!0,force:!0})),o.envVars.length>0&&re(e,{category:"CMS",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"CMS_PROVIDER",o.id)}import U from"fs";import N from"path";var si=N.join("apps","web"),mn=N.join("src","components","compliance"),St=N.join("src","app","[locale]");function ie(e){return N.join(e,si)}function ii(e){U.mkdirSync(e,{recursive:!0})}function Q(e,t){ii(N.dirname(e)),U.writeFileSync(e,t,"utf8")}function gn(e,t){let n=N.join(e,".env.example");if(U.existsSync(n)){if(U.readFileSync(n,"utf8").includes(t.split(`
477
+ `)}var ni=["design","iam","commerce","integrations","platform","ops","ai"];function Le(e,t){for(let o of ni){let r=kt.join(e,"packages",o,t);if(oe.existsSync(r))return r}let n=kt.join(e,"packages",t);return oe.existsSync(n)?n:null}function J(e,t){let n=Le(e,t);n&&oe.rmSync(n,{recursive:!0,force:!0})}function fo(e){return ot.existsSync(e)?ot.readFileSync(e,"utf-8"):null}function oi(e,t){let n=go.join(e,".env.example"),o=fo(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
+ `);ot.appendFileSync(n,s)}function ri(e,t,n){let o=go.join(e,".env.example"),r=fo(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?ot.writeFileSync(o,r.replace(s,`${t}="${n}"`)):ot.appendFileSync(o,`${t}="${n}"
479
+ `)}async function yo(e,t,n){let o=Le(e,"cache");if(t==="none"){o&&ot.rmSync(o,{recursive:!0,force:!0});return}let r=mo(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${Tt.map(s=>s.id).join(", ")}`);o&&(oi(e,r),ri(e,"CACHE_PROVIDER",t))}var Nt=[{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 So(e){return Nt.find(t=>t.id===e)}var xl=Nt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function ho(e,t,n="global"){let o=So(t);if(!o)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${Nt.map(r=>r.id).join(", ")}`);if(o.id==="none"){J(e,"captcha");return}o.envVars.length>0&&re(e,{category:"Captcha",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"CAPTCHA_PROVIDER",o.id)}import Lt from"fs";import si from"path";var Ot=[{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 Eo(e){return Ot.find(t=>t.id===e)}var Ol=Ot.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function vo(e,t,n="global"){let o=Eo(t);if(!o)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${Ot.map(s=>s.id).join(", ")}`);let r=si.join(e,"apps","studio");if(o.id==="none"){J(e,"sanity"),Lt.existsSync(r)&&Lt.rmSync(r,{recursive:!0,force:!0});return}o.id!=="sanity"&&(J(e,"sanity"),Lt.existsSync(r)&&Lt.rmSync(r,{recursive:!0,force:!0})),o.envVars.length>0&&re(e,{category:"CMS",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"CMS_PROVIDER",o.id)}import U from"fs";import N from"path";var ii=N.join("apps","web"),mn=N.join("src","components","compliance"),St=N.join("src","app","[locale]");function ie(e){return N.join(e,ii)}function ai(e){U.mkdirSync(e,{recursive:!0})}function Q(e,t){ai(N.dirname(e)),U.writeFileSync(e,t,"utf8")}function gn(e,t){let n=N.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 ht=`> **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`,ai=`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`,ci=`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
- `,ci=`export function IcpFooter() {
536
+ `,pi=`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
- `,pi=`export function PublicSecurityFooter() {
550
+ `,li=`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
- `,li=`"use client";
567
+ `,di=`"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
- `,di=`interface AigcDisclaimerProps {
721
+ `,ui=`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
- `,ui=`---
741
+ `,mi=`---
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
- `,mi=`---
886
+ `,gi=`---
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
- `,gi=`---
1005
+ `,fi=`---
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
@@ -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
- `,fi=`---
1087
+ `,yi=`---
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
- `,yi=`---
1152
+ `,Si=`---
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 Si(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=N.join(n,"src","components","compliance","Footer.tsx");Q(o,ai);let r=N.join(n,"src","components","compliance","README.md");Q(r,["# Compliance Components","",`Auto-generated by \`create-sailor\` for region: \`${t}\`.`,"","## Mounting the Footer","","```tsx",'import { Footer } from "@/components/compliance/Footer";','import { CookieBanner } from "@/components/compliance/CookieBanner";',"","export default function RootLayout({ children }) {"," return ("," <html>"," <body>"," {children}",` <Footer region="${t}" />`," <CookieBanner />"," </body>"," </html>"," );","}","```","","## Placeholders","","Policy MDX files contain `{{COMPANY_NAME}}`, `{{COMPANY_ADDRESS}}`,","`{{COMPANY_CONTACT_EMAIL}}`, `{{GOVERNING_JURISDICTION}}`, and","`{{AIGC_ALGORITHM_FILING_NUMBER}}`. These are filled by the `brand-apply` step.",""].join(`
1195
- `))}async function hi(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=N.join(n,"src","components","compliance","CookieBanner.tsx");Q(o,li)}async function Ei(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=N.join(n,St,"privacy","page.mdx");Q(o,ui)}async function vi(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=N.join(n,St,"terms","page.mdx");Q(o,mi)}async function bi(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,mn,"IcpFooter.tsx");Q(n,ci),gn(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 _i(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,mn,"PublicSecurityFooter.tsx");Q(n,pi),gn(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 Pi(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,mn,"AigcDisclaimer.tsx");Q(n,di),gn(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 wi(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,St,"aigc-disclosure","page.mdx");Q(n,gi)}async function Ai(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,St,"cross-border-data","page.mdx");Q(n,fi)}async function Ci(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,St,"pii-collection","page.mdx");Q(n,yi)}async function bo(e,t){try{await Si(e,t),await hi(e,t),await Ei(e,t),await vi(e,t),(t==="cn"||t==="hybrid")&&(await bi(e),await _i(e),await Pi(e),await wi(e),await Ai(e),await Ci(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 Ii from"fs";import xi from"path";async function _o(e,t){let n=xi.join(e,"nebutra.config.json");Ii.writeFileSync(n,JSON.stringify(t,null,2)+`
1199
- `)}import x from"fs";import Ue from"path";function Ri(e){x.existsSync(e)&&x.rmSync(e,{recursive:!0,force:!0})}function Po(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function Ti(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function wo(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 ki(e,t){let n=Ue.join(e,".env.example");x.existsSync(n)?x.appendFileSync(n,`
1200
- `+t):x.writeFileSync(n,t)}async function Ao(e,t,n){let o=Ue.join(e,"packages","platform","db");if(t==="none"){Ri(o);return}let r=Ue.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",ki(e,`# Database (${t})
1194
+ `;async function hi(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=N.join(n,"src","components","compliance","Footer.tsx");Q(o,ci);let r=N.join(n,"src","components","compliance","README.md");Q(r,["# Compliance Components","",`Auto-generated by \`create-sailor\` for region: \`${t}\`.`,"","## Mounting the Footer","","```tsx",'import { Footer } from "@/components/compliance/Footer";','import { CookieBanner } from "@/components/compliance/CookieBanner";',"","export default function RootLayout({ children }) {"," return ("," <html>"," <body>"," {children}",` <Footer region="${t}" />`," <CookieBanner />"," </body>"," </html>"," );","}","```","","## Placeholders","","Policy MDX files contain `{{COMPANY_NAME}}`, `{{COMPANY_ADDRESS}}`,","`{{COMPANY_CONTACT_EMAIL}}`, `{{GOVERNING_JURISDICTION}}`, and","`{{AIGC_ALGORITHM_FILING_NUMBER}}`. These are filled by the `brand-apply` step.",""].join(`
1195
+ `))}async function Ei(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=N.join(n,"src","components","compliance","CookieBanner.tsx");Q(o,di)}async function vi(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=N.join(n,St,"privacy","page.mdx");Q(o,mi)}async function bi(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=N.join(n,St,"terms","page.mdx");Q(o,gi)}async function _i(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,mn,"IcpFooter.tsx");Q(n,pi),gn(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 wi(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,mn,"PublicSecurityFooter.tsx");Q(n,li),gn(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 Pi(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,mn,"AigcDisclaimer.tsx");Q(n,ui),gn(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 Ai(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,St,"aigc-disclosure","page.mdx");Q(n,fi)}async function Ci(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,St,"cross-border-data","page.mdx");Q(n,yi)}async function Ii(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,St,"pii-collection","page.mdx");Q(n,Si)}async function bo(e,t){try{await hi(e,t),await Ei(e,t),await vi(e,t),await bi(e,t),(t==="cn"||t==="hybrid")&&(await _i(e),await wi(e),await Pi(e),await Ai(e),await Ci(e),await Ii(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 xi from"fs";import Ri from"path";async function _o(e,t){let n=Ri.join(e,"nebutra.config.json");xi.writeFileSync(n,JSON.stringify(t,null,2)+`
1199
+ `)}import x from"fs";import Ue from"path";function Ti(e){x.existsSync(e)&&x.rmSync(e,{recursive:!0,force:!0})}function wo(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function ki(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function Po(e){let t=e.replace(/^\s*extensions\s*=\s*\[[^\]]*\]\s*\n/gm,"");return t=t.replace(/previewFeatures\s*=\s*\[\s*"postgresqlExtensions"\s*\]\s*\n/g,""),t}function Ni(e,t){let n=Ue.join(e,".env.example");x.existsSync(n)?x.appendFileSync(n,`
1200
+ `+t):x.writeFileSync(n,t)}async function Ao(e,t,n){let o=Ue.join(e,"packages","platform","db");if(t==="none"){Ti(o);return}let r=Ue.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",Ni(e,`# Database (${t})
1201
1201
  DATABASE_URL="${s}"
1202
- `),!x.existsSync(r))return;let i=x.readFileSync(r,"utf8"),a=i;t==="mysql"?(a=Po(a,"mysql"),a=wo(a)):t==="sqlite"&&(a=Po(a,"sqlite"),a=Ti(a),a=wo(a)),a!==i&&x.writeFileSync(r,a)}function Ni(e){let t=Ue.join(e,".env.example");return x.existsSync(t)?x.readFileSync(t,"utf8"):""}function Oi(e,t,n,o){let r=Ue.join(e,".env.example"),s=Ni(e),i=o?`# ${o}
1202
+ `),!x.existsSync(r))return;let i=x.readFileSync(r,"utf8"),a=i;t==="mysql"?(a=wo(a,"mysql"),a=Po(a)):t==="sqlite"&&(a=wo(a,"sqlite"),a=ki(a),a=Po(a)),a!==i&&x.writeFileSync(r,a)}function Oi(e){let t=Ue.join(e,".env.example");return x.existsSync(t)?x.readFileSync(t,"utf8"):""}function Li(e,t,n,o){let r=Ue.join(e,".env.example"),s=Oi(e),i=o?`# ${o}
1203
1203
  ${t}="${n}"
1204
1204
  `:`${t}="${n}"
1205
1205
  `,a=new RegExp(`^\\s*${t}\\s*=.*$`,"m");if(a.test(s)){x.writeFileSync(r,s.replace(a,`${t}="${n}"`));return}s?x.appendFileSync(r,`
1206
- ${i}`):x.writeFileSync(r,i)}function Li(e,t){let n=Ue.join(e,"packages","platform","db","prisma","schema.prisma");if(!x.existsSync(n))return;let o=x.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(`
1206
+ ${i}`):x.writeFileSync(r,i)}function Ui(e,t){let n=Ue.join(e,"packages","platform","db","prisma","schema.prisma");if(!x.existsSync(n))return;let o=x.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
1207
  `),c=o.replace(r,`$1
1208
- ${a}$2`);x.writeFileSync(n,c)}function Ui(e){let t=Ue.join(e,"packages","platform","db","prisma","schema.prisma");if(!x.existsSync(t))return;let n=x.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)&&x.writeFileSync(t,n.replace(o,`$1 directUrl = env("DIRECT_URL")
1209
- `))}async function Co(e,t,n){if(!(t.id==="none"||t.id==="local")){for(let o of t.envVars){let r=o.placeholder.replace(/\$PROJECT/g,n);Oi(e,o.name,r,o.comment)}t.prismaDatasourceExtras&&t.prismaDatasourceExtras.length>0&&Li(e,t.prismaDatasourceExtras),t.keepDirectUrl&&Ui(e)}}import Pe from"fs";import De from"path";import{fileURLToPath as Di}from"url";var Mi=Di(import.meta.url),Io=De.dirname(Mi),Fi=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,xo=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function ji(e){let t=[De.join(Io,"..","templates","docs",e),De.join(Io,"..","..","templates","docs",e)];for(let n of t)if(Pe.existsSync(n))return n;return t[0]}async function Ro(e,t){if(t.framework==="none")return;if(!xo.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${xo.join(", ")}, none.`);let n=ji(t.framework),o=De.join(e,"apps","docs");if(!Pe.existsSync(n))throw new Error(`Docs template not found: ${n}`);To(n,o),ko(o,{"{PRODUCT_NAME}":t.projectName})}function To(e,t){Pe.mkdirSync(t,{recursive:!0});for(let n of Pe.readdirSync(e,{withFileTypes:!0})){let o=De.join(e,n.name),r=De.join(t,n.name);n.isDirectory()?To(o,r):Pe.copyFileSync(o,r)}}function ko(e,t){for(let n of Pe.readdirSync(e,{withFileTypes:!0})){let o=De.join(e,n.name);if(n.isDirectory())ko(o,t);else if(Fi.test(n.name)){let r=Pe.readFileSync(o,"utf-8");for(let[s,i]of Object.entries(t))r=r.split(s).join(i);Pe.writeFileSync(o,r)}}}import Fe from"fs";import Me from"path";var rt=[{id:"resend",name:"Resend",region:"global",envVars:["RESEND_API_KEY","RESEND_FROM"],docs:"https://resend.com/docs",pkg:"resend",pkgVersion:"^4.0.1"},{id:"postmark",name:"Postmark",region:"global",envVars:["POSTMARK_API_KEY","POSTMARK_FROM"],docs:"https://postmarkapp.com/developer",pkg:"postmark",pkgVersion:"^4.0.5"},{id:"ses",name:"AWS SES",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_SES_REGION","SES_FROM"],docs:"https://docs.aws.amazon.com/ses",pkg:"@aws-sdk/client-sesv2",pkgVersion:"^3.658.0"},{id:"aliyun-dm",name:"\u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001",region:"cn",envVars:["ALIYUN_DM_ACCESS_KEY","ALIYUN_DM_ACCESS_SECRET","ALIYUN_DM_ACCOUNT_NAME","ALIYUN_DM_FROM_ALIAS"],docs:"https://help.aliyun.com/product/29412.html",pkg:"@alicloud/dm20151123",pkgVersion:"^3.0.0"},{id:"tencent-ses",name:"\u817E\u8BAF\u4E91 SES",region:"cn",envVars:["TENCENT_SECRET_ID","TENCENT_SECRET_KEY","TENCENT_SES_FROM_EMAIL"],docs:"https://cloud.tencent.com/document/product/1288",pkg:"tencentcloud-sdk-nodejs-ses",pkgVersion:"^4.0.900"},{id:"netease",name:"\u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1",region:"cn",envVars:["NETEASE_USER","NETEASE_PASS","NETEASE_FROM"],docs:"https://qiye.163.com/help",pkg:"nodemailer",pkgVersion:"^6.9.15"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function No(e){return rt.find(t=>t.id===e)}var Ql=rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var je="@nebutra/email";function fn(e,t){Fe.mkdirSync(Me.dirname(e),{recursive:!0}),Fe.writeFileSync(e,t)}function Bi(e,t){let n=Me.join(e,".env.example");Fe.existsSync(n)?Fe.appendFileSync(n,`
1208
+ ${a}$2`);x.writeFileSync(n,c)}function Di(e){let t=Ue.join(e,"packages","platform","db","prisma","schema.prisma");if(!x.existsSync(t))return;let n=x.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)&&x.writeFileSync(t,n.replace(o,`$1 directUrl = env("DIRECT_URL")
1209
+ `))}async function Co(e,t,n){if(!(t.id==="none"||t.id==="local")){for(let o of t.envVars){let r=o.placeholder.replace(/\$PROJECT/g,n);Li(e,o.name,r,o.comment)}t.prismaDatasourceExtras&&t.prismaDatasourceExtras.length>0&&Ui(e,t.prismaDatasourceExtras),t.keepDirectUrl&&Di(e)}}import we from"fs";import De from"path";import{fileURLToPath as Mi}from"url";var Fi=Mi(import.meta.url),Io=De.dirname(Fi),ji=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,xo=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function Bi(e){let t=[De.join(Io,"..","templates","docs",e),De.join(Io,"..","..","templates","docs",e)];for(let n of t)if(we.existsSync(n))return n;return t[0]}async function Ro(e,t){if(t.framework==="none")return;if(!xo.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${xo.join(", ")}, none.`);let n=Bi(t.framework),o=De.join(e,"apps","docs");if(!we.existsSync(n))throw new Error(`Docs template not found: ${n}`);To(n,o),ko(o,{"{PRODUCT_NAME}":t.projectName})}function To(e,t){we.mkdirSync(t,{recursive:!0});for(let n of we.readdirSync(e,{withFileTypes:!0})){let o=De.join(e,n.name),r=De.join(t,n.name);n.isDirectory()?To(o,r):we.copyFileSync(o,r)}}function ko(e,t){for(let n of we.readdirSync(e,{withFileTypes:!0})){let o=De.join(e,n.name);if(n.isDirectory())ko(o,t);else if(ji.test(n.name)){let r=we.readFileSync(o,"utf-8");for(let[s,i]of Object.entries(t))r=r.split(s).join(i);we.writeFileSync(o,r)}}}import Fe from"fs";import Me from"path";var rt=[{id:"resend",name:"Resend",region:"global",envVars:["RESEND_API_KEY","RESEND_FROM"],docs:"https://resend.com/docs",pkg:"resend",pkgVersion:"^4.0.1"},{id:"postmark",name:"Postmark",region:"global",envVars:["POSTMARK_API_KEY","POSTMARK_FROM"],docs:"https://postmarkapp.com/developer",pkg:"postmark",pkgVersion:"^4.0.5"},{id:"ses",name:"AWS SES",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_SES_REGION","SES_FROM"],docs:"https://docs.aws.amazon.com/ses",pkg:"@aws-sdk/client-sesv2",pkgVersion:"^3.658.0"},{id:"aliyun-dm",name:"\u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001",region:"cn",envVars:["ALIYUN_DM_ACCESS_KEY","ALIYUN_DM_ACCESS_SECRET","ALIYUN_DM_ACCOUNT_NAME","ALIYUN_DM_FROM_ALIAS"],docs:"https://help.aliyun.com/product/29412.html",pkg:"@alicloud/dm20151123",pkgVersion:"^3.0.0"},{id:"tencent-ses",name:"\u817E\u8BAF\u4E91 SES",region:"cn",envVars:["TENCENT_SECRET_ID","TENCENT_SECRET_KEY","TENCENT_SES_FROM_EMAIL"],docs:"https://cloud.tencent.com/document/product/1288",pkg:"tencentcloud-sdk-nodejs-ses",pkgVersion:"^4.0.900"},{id:"netease",name:"\u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1",region:"cn",envVars:["NETEASE_USER","NETEASE_PASS","NETEASE_FROM"],docs:"https://qiye.163.com/help",pkg:"nodemailer",pkgVersion:"^6.9.15"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function No(e){return rt.find(t=>t.id===e)}var ed=rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var je="@nebutra/email";function fn(e,t){Fe.mkdirSync(Me.dirname(e),{recursive:!0}),Fe.writeFileSync(e,t)}function $i(e,t){let n=Me.join(e,".env.example");Fe.existsSync(n)?Fe.appendFileSync(n,`
1210
1210
  `+t):Fe.writeFileSync(n,t)}function Vi(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 $i=`/**
1213
+ `}var Ki=`/**
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 Ki(){return`/**
1233
+ `;function Yi(){return`/**
1234
1234
  * @${je.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 Yi(){return`/**
1272
+ `}function qi(){return`/**
1273
1273
  * @${je.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 qi(){return`/**
1310
+ `}function Gi(){return`/**
1311
1311
  * @${je.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 Gi(){return`/**
1366
+ `}function Hi(){return`/**
1367
1367
  * @${je.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 Hi(){return`/**
1416
+ `}function Wi(){return`/**
1417
1417
  * @${je.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 Xi(){return`/**
1465
1465
  * @${je.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 Xi(e){switch(e){case"resend":return Ki();case"postmark":return Yi();case"ses":return qi();case"aliyun-dm":return Gi();case"tencent-ses":return Hi();case"netease":return Wi();case"none":return`export {};
1503
- `}}function zi(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:je,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 Oo(e,t,n){if(t==="none")return;let o=No(t);if(!o)throw new Error(`Unknown email provider "${t}". Valid ids: ${rt.map(i=>i.id).join(", ")}`);let r=Me.join(e,"packages","email"),s=Me.join(r,"src");Fe.existsSync(s)&&Fe.rmSync(s,{recursive:!0,force:!0}),fn(Me.join(r,"package.json"),zi(o)),fn(Me.join(s,"types.ts"),$i),fn(Me.join(s,"index.ts"),Xi(o.id)),Bi(e,Vi(o))}import ue from"fs";import Lo from"path";function Ji(e,t){return new RegExp(`^\\s*${t}\\s*=`,"m").test(e)}function Uo(e){return e.endsWith(`
1502
+ `}function zi(e){switch(e){case"resend":return Yi();case"postmark":return qi();case"ses":return Gi();case"aliyun-dm":return Hi();case"tencent-ses":return Wi();case"netease":return Xi();case"none":return`export {};
1503
+ `}}function Ji(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:je,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 Oo(e,t,n){if(t==="none")return;let o=No(t);if(!o)throw new Error(`Unknown email provider "${t}". Valid ids: ${rt.map(i=>i.id).join(", ")}`);let r=Me.join(e,"packages","email"),s=Me.join(r,"src");Fe.existsSync(s)&&Fe.rmSync(s,{recursive:!0,force:!0}),fn(Me.join(r,"package.json"),Ji(o)),fn(Me.join(s,"types.ts"),Ki),fn(Me.join(s,"index.ts"),zi(o.id)),$i(e,Vi(o))}import ue from"fs";import Lo from"path";function Qi(e,t){return new RegExp(`^\\s*${t}\\s*=`,"m").test(e)}function Uo(e){return e.endsWith(`
1505
1505
  `)?e:`${e}
1506
1506
  `}async function Do(e,t){let n=Lo.join(e,".env"),o=Lo.join(e,".env.local"),r=ue.existsSync(n)?ue.readFileSync(n,"utf8"):"",s=ue.existsSync(o)?ue.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=>!Ji(i,p.name)).map(p=>`${p.name}="${p.value}"`);if(a.length===0)return;let c=`# Automatically injected by create-sailor
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=>!Qi(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
1510
  `;try{let p=ue.readFileSync(o,"utf8"),d=Uo(p);ue.writeFileSync(o,`${d}
1511
1511
  ${c}`)}catch{try{ue.writeFileSync(o,c,{flag:"wx"})}catch{let p=ue.readFileSync(o,"utf8");ue.writeFileSync(o,`${Uo(p)}
1512
- ${c}`)}}}import Fo from"crypto";import Et from"fs";import Mo from"path";function Be(e){return Fo.randomBytes(e).toString("base64").replace(/=+$/,"")}function Qi(e){return Fo.randomBytes(e).toString("hex")}function Zi(){return{AUTH_SECRET:Be(32),NEXTAUTH_SECRET:Be(32),BETTER_AUTH_SECRET:Be(32),JWT_SECRET:Be(32),WEBHOOK_SECRET:Qi(16),ENCRYPTION_KEY:Be(32),API_SECRET_KEY:Be(32),SESSION_SECRET:Be(32)}}function ea(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function ta(e,t,n){let o=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=ea(n);return e.replace(o,`${t}="${r}"`)}async function jo(e){let t=Mo.join(e,".env.example"),n=Mo.join(e,".env.local");if(!Et.existsSync(t))return null;try{let o=Et.readFileSync(t,"utf8"),r=Zi(),i=Et.existsSync(n)?Et.readFileSync(n,"utf8"):o;for(let a of Object.keys(r))i=ta(i,a,r[a]);return Et.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 Ut=[{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 Bo(e){return Ut.find(t=>t.id===e)}var dd=Ut.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Vo(e,t,n="global"){let o=Bo(t);if(!o)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${Ut.map(r=>r.id).join(", ")}`);if(o.id==="none"){J(e,"feature-flags");return}o.envVars.length>0&&re(e,{category:"Feature Flags",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"FEATURE_FLAGS_PROVIDER",o.id)}import{execFileSync as qo}from"child_process";import O from"fs";import na from"os";import ae from"path";import oa from"ignore";var ra={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 sa(){let e=process.env.SAILOR_TEMPLATE_LOCAL_DIR;if(!(!e||e.trim().length===0))return ae.resolve(e.trim())}var ia=new Set(["node_modules",".git","dist",".next",".turbo"]);function aa(e,t){if(!O.statSync(e).isDirectory())throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR is not a directory: ${e}`);O.cpSync(e,t,{recursive:!0,dereference:!0,filter:o=>{let r=ae.basename(o);return!ia.has(r)}})}function ca(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function pa(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function Go(e){return/^[0-9a-f]{7,40}$/i.test(e)}function la(e,t){let n=`https://github.com/${e}.git`,o=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of o)try{let s=qo("git",["ls-remote",n,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!s)continue;let[i]=s.split(/\s+/);if(Go(i))return i}catch{}return null}async function da(e,t){if(Go(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=la(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 Ho(e,t,n){let o=O.readdirSync(t,{withFileTypes:!0});for(let r of o){if(r.name==="node_modules"||r.name===".git")continue;let s=ae.join(t,r.name),i=ae.relative(e,s).split(ae.sep).join("/");r.isDirectory()?(n.push(i+"/"),Ho(e,s,n)):n.push(i)}}function $o(e){let t=ae.join(e,".templateignore");if(!O.existsSync(t))return;let n=O.readFileSync(t,"utf8"),o=oa().add(n),r=[];Ho(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=ae.join(e,c);try{O.existsSync(p)&&O.rmSync(p,{recursive:!0,force:!0})}catch{}}try{O.existsSync(t)&&O.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)`);O.writeFileSync(t,o);let r=O.statSync(t);if(r.size!==o.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${o.byteLength})`);return r.size}function Yo(e,t){qo("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function yn(e){try{let t=O.readdirSync(e);for(let n of t)O.rmSync(ae.join(e,n),{recursive:!0,force:!0})}catch{}}async function ua(e,t){let n=O.mkdtempSync(ae.join(na.tmpdir(),"create-sailor-")),o=ae.join(n,"template.tar.gz");try{let r=await da(e.repo,e.ref);await Ko(pa(e.repo,r),o),Yo(o,t)}catch(r){if(!e.allowMutableFallback)throw r;yn(t),await Ko(ca(e.repo,e.ref),o),Yo(o,t)}finally{O.rmSync(n,{recursive:!0,force:!0})}}async function Wo(e){O.mkdirSync(e,{recursive:!0});let t=sa();if(t){if(!O.existsSync(t))throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR does not exist: ${t}`);yn(e),aa(t,e);try{$o(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=ra[s];try{if(await ua(i,e),i.applyIgnore)try{$o(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)),yn(e)}}throw new Error(`Failed to download the template from any source. Last error: ${r?.message??"unknown"}
1512
+ ${c}`)}}}import Fo from"crypto";import Et from"fs";import Mo from"path";function Be(e){return Fo.randomBytes(e).toString("base64").replace(/=+$/,"")}function Zi(e){return Fo.randomBytes(e).toString("hex")}function ea(){return{AUTH_SECRET:Be(32),NEXTAUTH_SECRET:Be(32),BETTER_AUTH_SECRET:Be(32),JWT_SECRET:Be(32),WEBHOOK_SECRET:Zi(16),ENCRYPTION_KEY:Be(32),API_SECRET_KEY:Be(32),SESSION_SECRET:Be(32)}}function ta(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function na(e,t,n){let o=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=ta(n);return e.replace(o,`${t}="${r}"`)}async function jo(e){let t=Mo.join(e,".env.example"),n=Mo.join(e,".env.local");if(!Et.existsSync(t))return null;try{let o=Et.readFileSync(t,"utf8"),r=ea(),i=Et.existsSync(n)?Et.readFileSync(n,"utf8"):o;for(let a of Object.keys(r))i=na(i,a,r[a]);return Et.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 Ut=[{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 Bo(e){return Ut.find(t=>t.id===e)}var md=Ut.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function $o(e,t,n="global"){let o=Bo(t);if(!o)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${Ut.map(r=>r.id).join(", ")}`);if(o.id==="none"){J(e,"feature-flags");return}o.envVars.length>0&&re(e,{category:"Feature Flags",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"FEATURE_FLAGS_PROVIDER",o.id)}import{execFileSync as qo}from"child_process";import O from"fs";import oa from"os";import ae from"path";import ra from"ignore";var sa={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 ia(){let e=process.env.SAILOR_TEMPLATE_LOCAL_DIR;if(!(!e||e.trim().length===0))return ae.resolve(e.trim())}var aa=new Set(["node_modules",".git","dist",".next",".turbo"]);function ca(e,t){if(!O.statSync(e).isDirectory())throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR is not a directory: ${e}`);O.cpSync(e,t,{recursive:!0,dereference:!0,filter:o=>{let r=ae.basename(o);return!aa.has(r)}})}function pa(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function la(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function Go(e){return/^[0-9a-f]{7,40}$/i.test(e)}function da(e,t){let n=`https://github.com/${e}.git`,o=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of o)try{let s=qo("git",["ls-remote",n,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!s)continue;let[i]=s.split(/\s+/);if(Go(i))return i}catch{}return null}async function ua(e,t){if(Go(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=da(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 Ho(e,t,n){let o=O.readdirSync(t,{withFileTypes:!0});for(let r of o){if(r.name==="node_modules"||r.name===".git")continue;let s=ae.join(t,r.name),i=ae.relative(e,s).split(ae.sep).join("/");r.isDirectory()?(n.push(i+"/"),Ho(e,s,n)):n.push(i)}}function Vo(e){let t=ae.join(e,".templateignore");if(!O.existsSync(t))return;let n=O.readFileSync(t,"utf8"),o=ra().add(n),r=[];Ho(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=ae.join(e,c);try{O.existsSync(p)&&O.rmSync(p,{recursive:!0,force:!0})}catch{}}try{O.existsSync(t)&&O.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)`);O.writeFileSync(t,o);let r=O.statSync(t);if(r.size!==o.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${o.byteLength})`);return r.size}function Yo(e,t){qo("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function yn(e){try{let t=O.readdirSync(e);for(let n of t)O.rmSync(ae.join(e,n),{recursive:!0,force:!0})}catch{}}async function ma(e,t){let n=O.mkdtempSync(ae.join(oa.tmpdir(),"create-sailor-")),o=ae.join(n,"template.tar.gz");try{let r=await ua(e.repo,e.ref);await Ko(la(e.repo,r),o),Yo(o,t)}catch(r){if(!e.allowMutableFallback)throw r;yn(t),await Ko(pa(e.repo,e.ref),o),Yo(o,t)}finally{O.rmSync(n,{recursive:!0,force:!0})}}async function Wo(e){O.mkdirSync(e,{recursive:!0});let t=ia();if(t){if(!O.existsSync(t))throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR does not exist: ${t}`);yn(e),ca(t,e);try{Vo(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=sa[s];try{if(await ma(i,e),i.applyIgnore)try{Vo(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)),yn(e)}}throw new Error(`Failed to download the template from any source. Last error: ${r?.message??"unknown"}
1513
1513
 
1514
1514
  Ensure you have internet access and 'tar' installed.
1515
- You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import Dt from"fs";import Sn from"path";var ma="node scripts/governance/lint-no-raw-inputs.mjs",ga="node scripts/governance/lint-repository-seam.mjs",fa="node scripts/governance/lint-brand-literals.mjs",ya="node scripts/governance/lint-microcopy.mjs",Sa=/\bnode\s+scripts\/(governance\/)?lint-[\w-]+\.mjs/g,ha=/\bnode\s+scripts\/lint-[\w-]+\.mjs/,Ea={scanRoots:["apps"],primitivesImport:"@nebutra/ui/primitives",whitelist:["/storybook/src/stories/","/design-docs/src/components/previews/","/sailor-docs/src/components/previews/","\\.test\\.tsx?$","/__tests__/"]},va={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"]},ba={scanRoots:["apps/web/src"],excludePaths:["/api/","\\.test\\.tsx?$","/__tests__/","/storybook/src/stories/","/design-docs/","/sailor-docs/"],bannedPatterns:[],allowlist:[]},Xo={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:[]},_a=["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 Pa(e,t){let n=(e??"").replace(Sa,"").split("&&").map(r=>r.trim()).filter(Boolean).join(" && ");return[n.length>0?n:"biome check .",...t].join(" && ")}function wa(e){let t=new RegExp(Xo.allowExpressions.join("|"));return _a.filter(n=>{try{return t.test(Dt.readFileSync(Sn.join(e,n),"utf8"))}catch{return!1}})}async function zo(e,t){let n=t.database!=="none",o=[ma];n&&o.push(ga),o.push(fa),o.push(ya);let r={...Xo,allowlist:wa(e)},s={rawInputs:Ea,brandLiterals:r,microcopyRules:ba};n&&(s.repositorySeam=va);let i=Sn.join(e,"governance.config.json");Dt.writeFileSync(i,JSON.stringify(s,null,2)+`
1516
- `);let a=Sn.join(e,"package.json"),c;try{c=Dt.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[d,u]of Object.entries(p.scripts))d!=="lint"&&typeof u=="string"&&ha.test(u)&&delete p.scripts[d];p.scripts.lint=Pa(p.scripts.lint,o),Dt.writeFileSync(a,JSON.stringify(p,null,2)+`
1517
- `)}return{lints:o,configWritten:!0}}import Z from"fs";import ce from"path";import{fileURLToPath as Aa}from"url";var Ca=Aa(import.meta.url),Jo=ce.dirname(Ca),Qo="scaffold-meta.json",Zo=".nebutra";function Ia(e){if(e)return e;let t=[ce.join(Jo,"..","templates"),ce.join(Jo,"..","..","templates")];for(let n of t)if(Z.existsSync(n))return n;return t[0]}function er(e,t){let n=[],o=Ia(t.templatesRoot),r=ce.join(e,"LICENSE");if(Z.existsSync(r)){let p=Z.readFileSync(r,"utf-8").slice(0,256);(/GNU AFFERO GENERAL PUBLIC LICENSE/i.test(p)||/Functional Source License/i.test(p))&&(Z.renameSync(r,ce.join(e,"LICENSE-UPSTREAM-REFERENCE.md")),n.push("LICENSE-UPSTREAM-REFERENCE.md (preserved upstream licence)"))}let s=ce.join(o,"LICENSE-SCAFFOLD.md");if(!Z.existsSync(s))throw new Error(`LICENSE-SCAFFOLD.md template missing at ${s}; cannot emit license.`);Z.copyFileSync(s,ce.join(e,"LICENSE")),n.push("LICENSE");let i={schemaVersion:1,cliVersion:t.cliVersion,scaffoldedAt:new Date().toISOString(),projectName:t.projectName,purpose:"Records which `create-sailor` version produced this project, for support triage. Provenance only: the MIT licence in LICENSE applies unconditionally and does not depend on this file. Deleting it costs you nothing.",license:{tier:"mit-scaffold",file:"LICENSE"}},a=ce.join(e,Zo);Z.mkdirSync(a,{recursive:!0}),Z.writeFileSync(ce.join(a,Qo),`${JSON.stringify(i,null,2)}
1515
+ You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import Dt from"fs";import Sn from"path";var ga="node scripts/governance/lint-no-raw-inputs.mjs",fa="node scripts/governance/lint-repository-seam.mjs",ya="node scripts/governance/lint-brand-literals.mjs",Sa="node scripts/governance/lint-microcopy.mjs",ha=/\bnode\s+scripts\/(governance\/)?lint-[\w-]+\.mjs/g,Ea=/\bnode\s+scripts\/lint-[\w-]+\.mjs/,va={scanRoots:["apps"],primitivesImport:"@nebutra/ui/primitives",whitelist:["/storybook/src/stories/","/design-docs/src/components/previews/","/sailor-docs/src/components/previews/","\\.test\\.tsx?$","/__tests__/"]},ba={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"]},_a={scanRoots:["apps/web/src"],excludePaths:["/api/","\\.test\\.tsx?$","/__tests__/","/storybook/src/stories/","/design-docs/","/sailor-docs/"],bannedPatterns:[],allowlist:[]},Xo={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:[]},wa=["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 Pa(e,t){let n=(e??"").replace(ha,"").split("&&").map(r=>r.trim()).filter(Boolean).join(" && ");return[n.length>0?n:"biome check .",...t].join(" && ")}function Aa(e){let t=new RegExp(Xo.allowExpressions.join("|"));return wa.filter(n=>{try{return t.test(Dt.readFileSync(Sn.join(e,n),"utf8"))}catch{return!1}})}async function zo(e,t){let n=t.database!=="none",o=[ga];n&&o.push(fa),o.push(ya),o.push(Sa);let r={...Xo,allowlist:Aa(e)},s={rawInputs:va,brandLiterals:r,microcopyRules:_a};n&&(s.repositorySeam=ba);let i=Sn.join(e,"governance.config.json");Dt.writeFileSync(i,JSON.stringify(s,null,2)+`
1516
+ `);let a=Sn.join(e,"package.json"),c;try{c=Dt.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[d,u]of Object.entries(p.scripts))d!=="lint"&&typeof u=="string"&&Ea.test(u)&&delete p.scripts[d];p.scripts.lint=Pa(p.scripts.lint,o),Dt.writeFileSync(a,JSON.stringify(p,null,2)+`
1517
+ `)}return{lints:o,configWritten:!0}}import Z from"fs";import ce from"path";import{fileURLToPath as Ca}from"url";var Ia=Ca(import.meta.url),Jo=ce.dirname(Ia),Qo="scaffold-meta.json",Zo=".nebutra";function xa(e){if(e)return e;let t=[ce.join(Jo,"..","templates"),ce.join(Jo,"..","..","templates")];for(let n of t)if(Z.existsSync(n))return n;return t[0]}function er(e,t){let n=[],o=xa(t.templatesRoot),r=ce.join(e,"LICENSE");if(Z.existsSync(r)){let p=Z.readFileSync(r,"utf-8").slice(0,256);(/GNU AFFERO GENERAL PUBLIC LICENSE/i.test(p)||/Functional Source License/i.test(p))&&(Z.renameSync(r,ce.join(e,"LICENSE-UPSTREAM-REFERENCE.md")),n.push("LICENSE-UPSTREAM-REFERENCE.md (preserved upstream licence)"))}let s=ce.join(o,"LICENSE-SCAFFOLD.md");if(!Z.existsSync(s))throw new Error(`LICENSE-SCAFFOLD.md template missing at ${s}; cannot emit license.`);Z.copyFileSync(s,ce.join(e,"LICENSE")),n.push("LICENSE");let i={schemaVersion:1,cliVersion:t.cliVersion,scaffoldedAt:new Date().toISOString(),projectName:t.projectName,purpose:"Records which `create-sailor` version produced this project, for support triage. Provenance only: the MIT licence in LICENSE applies unconditionally and does not depend on this file. Deleting it costs you nothing.",license:{tier:"mit-scaffold",file:"LICENSE"}},a=ce.join(e,Zo);Z.mkdirSync(a,{recursive:!0}),Z.writeFileSync(ce.join(a,Qo),`${JSON.stringify(i,null,2)}
1518
1518
  `),n.push(`${Zo}/${Qo}`);let c=ce.join(e,"README.md");if(Z.existsSync(c)){let p=Z.readFileSync(c,"utf-8");p.includes("Scaffolded by `create-sailor`")||(Z.writeFileSync(c,`> **License notice:** Scaffolded by \`create-sailor\`. The Nebutra-Sailor
1519
1519
  > code in this project is [MIT licensed](./LICENSE) \u2014 commercial use, closed
1520
1520
  > source, no fee, no attribution required. The upstream monorepo is
1521
1521
  > FSL-1.1-ALv2 \u2014 see \`LICENSE-UPSTREAM-REFERENCE.md\`.
1522
1522
 
1523
- `+p),n.push("README.md (prepended license notice)"))}return{wrote:n}}import Ve from"fs";import hn from"path";async function tr(e,t){let n=hn.join(e,"packages","mcp");if(t==="off"){Ve.existsSync(n)&&Ve.rmSync(n,{recursive:!0,force:!0});let r=hn.join(e,"packages","cli","src","commands","mcp-server.ts");Ve.existsSync(r)&&Ve.rmSync(r,{force:!0});return}let o=hn.join(e,".env.example");if(Ve.existsSync(o)){let r=Ve.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
- `);Ve.appendFileSync(o,i)}}}import vt from"fs";import nr from"path";async function or(e,t,n){let o=nr.join(e,"packages","metering"),r;if(t==="auto"?r=n!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){vt.existsSync(o)&&vt.rmSync(o,{recursive:!0,force:!0});return}let s=nr.join(e,".env.example");if(!vt.existsSync(s))return;let i=vt.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
- `);vt.appendFileSync(s,c)}}import me from"fs";import F from"path";var rr=[{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=rr.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function sr(e){return rr.find(t=>t.id===e)}var En={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 xa(e){me.mkdirSync(e,{recursive:!0})}function vn(e,t){let n=F.join(e,"package.json");if(!me.existsSync(n))return;let o;try{o=JSON.parse(me.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};me.writeFileSync(n,JSON.stringify(i,null,2)+`
1526
- `)}function pe(e,t){xa(F.dirname(e)),me.writeFileSync(e,t)}function bt(e,t){let n=F.join(e,".env.example");me.existsSync(n)?me.appendFileSync(n,`
1527
- `+t):me.writeFileSync(n,t)}function Ra(e){let t=`import * as Sentry from "@sentry/nextjs";
1523
+ `+p),n.push("README.md (prepended license notice)"))}return{wrote:n}}import $e from"fs";import hn from"path";async function tr(e,t){let n=hn.join(e,"packages","mcp");if(t==="off"){$e.existsSync(n)&&$e.rmSync(n,{recursive:!0,force:!0});let r=hn.join(e,"packages","cli","src","commands","mcp-server.ts");$e.existsSync(r)&&$e.rmSync(r,{force:!0});return}let o=hn.join(e,".env.example");if($e.existsSync(o)){let r=$e.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
+ `);$e.appendFileSync(o,i)}}}import vt from"fs";import nr from"path";async function or(e,t,n){let o=nr.join(e,"packages","metering"),r;if(t==="auto"?r=n!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){vt.existsSync(o)&&vt.rmSync(o,{recursive:!0,force:!0});return}let s=nr.join(e,".env.example");if(!vt.existsSync(s))return;let i=vt.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
+ `);vt.appendFileSync(s,c)}}import me from"fs";import F from"path";var rr=[{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:""}],Md=rr.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function sr(e){return rr.find(t=>t.id===e)}var En={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 Ra(e){me.mkdirSync(e,{recursive:!0})}function vn(e,t){let n=F.join(e,"package.json");if(!me.existsSync(n))return;let o;try{o=JSON.parse(me.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};me.writeFileSync(n,JSON.stringify(i,null,2)+`
1526
+ `)}function pe(e,t){Ra(F.dirname(e)),me.writeFileSync(e,t)}function bt(e,t){let n=F.join(e,".env.example");me.existsSync(n)?me.appendFileSync(n,`
1527
+ `+t):me.writeFileSync(n,t)}function Ta(e){let t=`import * as Sentry from "@sentry/nextjs";
1528
1528
 
1529
1529
  Sentry.init({
1530
1530
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
@@ -1567,14 +1567,14 @@ export async function register() {
1567
1567
  }
1568
1568
 
1569
1569
  export { captureRequestError as onRequestError } from "@sentry/nextjs";
1570
- `;pe(F.join(e,"sentry.client.config.ts"),t),pe(F.join(e,"sentry.server.config.ts"),n),pe(F.join(e,"sentry.edge.config.ts"),o),pe(F.join(e,"instrumentation.ts"),r)}function Ta(){return`# Sentry \u2014 error tracking + performance monitoring
1570
+ `;pe(F.join(e,"sentry.client.config.ts"),t),pe(F.join(e,"sentry.server.config.ts"),n),pe(F.join(e,"sentry.edge.config.ts"),o),pe(F.join(e,"instrumentation.ts"),r)}function ka(){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 ka(e){let t=`/**
1577
+ `}function Na(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
- `;pe(F.join(e,"instrumentation.ts"),t),pe(F.join(e,"src","lib","monitoring","datadog-rum.ts"),n)}function Na(){return`# Datadog \u2014 APM + RUM
1625
+ `;pe(F.join(e,"instrumentation.ts"),t),pe(F.join(e,"src","lib","monitoring","datadog-rum.ts"),n)}function Oa(){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 Oa(e){let t=`/**
1640
+ `}function La(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
- `;pe(F.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),pe(F.join(e,"src","lib","monitoring","bugsnag.client.tsx"),n)}function La(){return`# Bugsnag \u2014 error tracking
1689
+ `;pe(F.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),pe(F.join(e,"src","lib","monitoring","bugsnag.client.tsx"),n)}function Ua(){return`# Bugsnag \u2014 error tracking
1690
1690
  BUGSNAG_API_KEY=
1691
1691
  NEXT_PUBLIC_BUGSNAG_API_KEY=
1692
1692
  APP_VERSION=
1693
- `}function Ua(e){pe(F.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1693
+ `}function Da(e){pe(F.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 Da(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1714
+ `)}function Ma(){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 Ma(e){pe(F.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1718
+ `}function Fa(e){pe(F.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 Fa(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1736
+ `)}function ja(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1737
1737
  TINGYUN_LICENSE_KEY=
1738
1738
  NEXT_PUBLIC_TINGYUN_APP_KEY=
1739
- `}async function ir(e,t,n="global"){let o=sr(t);if(!o||o.id==="none")return;let r=F.join(e,"apps","web");if(!me.existsSync(r))return;let s=o.id;try{switch(s){case"sentry":Ra(r),vn(r,En.sentry),bt(e,Ta());return;case"datadog":ka(r),vn(r,En.datadog),bt(e,Na());return;case"bugsnag":Oa(r),vn(r,En.bugsnag),bt(e,La());return;case"aliyun-arms":Ua(r),bt(e,Da());return;case"tingyun":Ma(r),bt(e,Fa());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 Mt=[{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 ar(e){return Mt.find(t=>t.id===e)}var Vd=Mt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function cr(e,t,n="global"){let o=ar(t);if(!o)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${Mt.map(r=>r.id).join(", ")}`);if(o.id==="none"){J(e,"notifications");return}o.envVars.length>0&&re(e,{category:"Notifications",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"NOTIFICATIONS_PROVIDER",o.id)}import bn from"fs";import ja from"path";async function pr(e,t){let n=ja.join(e,"package.json");if(bn.existsSync(n)){let o=bn.readFileSync(n,"utf8"),r=JSON.parse(o);r.name=t,r.version="0.1.0",bn.writeFileSync(n,JSON.stringify(r,null,2)+`
1740
- `)}}import Ft from"fs";import st from"path";import{fileURLToPath as Ba}from"url";var Va=Ba(import.meta.url),lr=st.dirname(Va);function $a(){let e=[st.join(lr,"..","templates","orm","drizzle"),st.join(lr,"..","..","templates","orm","drizzle")];for(let t of e)if(Ft.existsSync(t))return t;return null}function dr(e,t){Ft.mkdirSync(t,{recursive:!0});for(let n of Ft.readdirSync(e,{withFileTypes:!0})){let o=st.join(e,n.name),r=st.join(t,n.name);n.isDirectory()?dr(o,r):Ft.copyFileSync(o,r)}}async function ur(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=$a();if(!o)return{applied:!1,reason:"Drizzle template directory not found in package \u2014 bundling error"};let r=st.join(e,"packages","platform","db-drizzle");return dr(o,r),{applied:!0}}import ge from"fs";import _t from"path";var Ka=["stripe","lemonsqueezy","chinapay","polar"];function mr(e){ge.existsSync(e)&&ge.rmSync(e,{recursive:!0,force:!0})}function Ya(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function qa(e,t){let n=_t.join(e,".env.example");ge.existsSync(n)?ge.appendFileSync(n,`
1741
- `+t):ge.writeFileSync(n,t)}function Ga(e){switch(e){case"stripe":return`# Stripe
1739
+ `}async function ir(e,t,n="global"){let o=sr(t);if(!o||o.id==="none")return;let r=F.join(e,"apps","web");if(!me.existsSync(r))return;let s=o.id;try{switch(s){case"sentry":Ta(r),vn(r,En.sentry),bt(e,ka());return;case"datadog":Na(r),vn(r,En.datadog),bt(e,Oa());return;case"bugsnag":La(r),vn(r,En.bugsnag),bt(e,Ua());return;case"aliyun-arms":Da(r),bt(e,Ma());return;case"tingyun":Fa(r),bt(e,ja());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 Mt=[{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 ar(e){return Mt.find(t=>t.id===e)}var Kd=Mt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function cr(e,t,n="global"){let o=ar(t);if(!o)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${Mt.map(r=>r.id).join(", ")}`);if(o.id==="none"){J(e,"notifications");return}o.envVars.length>0&&re(e,{category:"Notifications",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"NOTIFICATIONS_PROVIDER",o.id)}import bn from"fs";import Ba from"path";async function pr(e,t){let n=Ba.join(e,"package.json");if(bn.existsSync(n)){let o=bn.readFileSync(n,"utf8"),r=JSON.parse(o);r.name=t,r.version="0.1.0",bn.writeFileSync(n,JSON.stringify(r,null,2)+`
1740
+ `)}}import Ft from"fs";import st from"path";import{fileURLToPath as $a}from"url";var Va=$a(import.meta.url),lr=st.dirname(Va);function Ka(){let e=[st.join(lr,"..","templates","orm","drizzle"),st.join(lr,"..","..","templates","orm","drizzle")];for(let t of e)if(Ft.existsSync(t))return t;return null}function dr(e,t){Ft.mkdirSync(t,{recursive:!0});for(let n of Ft.readdirSync(e,{withFileTypes:!0})){let o=st.join(e,n.name),r=st.join(t,n.name);n.isDirectory()?dr(o,r):Ft.copyFileSync(o,r)}}async function ur(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=Ka();if(!o)return{applied:!1,reason:"Drizzle template directory not found in package \u2014 bundling error"};let r=st.join(e,"packages","platform","db-drizzle");return dr(o,r),{applied:!0}}import ge from"fs";import _t from"path";var Ya=["stripe","lemonsqueezy","chinapay","polar"];function mr(e){ge.existsSync(e)&&ge.rmSync(e,{recursive:!0,force:!0})}function qa(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function Ga(e,t){let n=_t.join(e,".env.example");ge.existsSync(n)?ge.appendFileSync(n,`
1741
+ `+t):ge.writeFileSync(n,t)}function Ha(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,12 +1753,12 @@ CHINAPAY_WECHAT_ENABLED=true
1753
1753
  CHINAPAY_APP_ID=
1754
1754
  CHINAPAY_APP_SECRET=
1755
1755
  CHINAPAY_ALIPAY_ENABLED=true
1756
- `}}async function gr(e,t){let n=_t.join(e,"packages","commerce","billing");if(!ge.existsSync(n))return;if(t==="none"){mr(n);return}let o=_t.join(n,"src"),r=new Set(Ya(t));for(let i of Ka)r.has(i)||mr(_t.join(o,i));let s=_t.join(o,"checkout","types.ts");if(ge.existsSync(s)){let i=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",a=ge.readFileSync(s,"utf8"),c=a.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${i}";`);c!==a&&ge.writeFileSync(s,c)}qa(e,Ga(t))}import we from"fs";import it from"path";var Sr=new Set(["siliconflow","volcengine-ark","bailian","moonshot","sensetime"]),_n=/@sailor:([^\s*]+)/;function Ha(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=>Sr.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 fr(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function yr(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function hr(e,t){let n=e.split(`
1757
- `),o=[],r=e.includes("#"),s=0;for(;s<n.length;){let i=n[s],a=i.match(_n);if(!a){o.push(i),s++;continue}let{marker:c,keep:p}=Ha(a[1],t);if(c==="registry-entries"){o.push(r?yr(i):fr(i)),s++;continue}if(p){let d=r?yr(i):fr(i);d.trim().length>0&&o.push(d);let u=s+1;for(;u<n.length&&n[u].trim()!==""&&!_n.test(n[u]);)o.push(n[u]),u++;u<n.length&&n[u].trim()===""&&(o.push(n[u]),u++),s=u}else{let d=s+1;for(;d<n.length&&n[d].trim()!==""&&!_n.test(n[d]);)d++;d<n.length&&n[d].trim()===""&&d++,s=d}}return Wa(o.join(`
1758
- `),t)}function Wa(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(`
1756
+ `}}async function gr(e,t){let n=_t.join(e,"packages","commerce","billing");if(!ge.existsSync(n))return;if(t==="none"){mr(n);return}let o=_t.join(n,"src"),r=new Set(qa(t));for(let i of Ya)r.has(i)||mr(_t.join(o,i));let s=_t.join(o,"checkout","types.ts");if(ge.existsSync(s)){let i=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",a=ge.readFileSync(s,"utf8"),c=a.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${i}";`);c!==a&&ge.writeFileSync(s,c)}Ga(e,Ha(t))}import Pe from"fs";import it from"path";var Sr=new Set(["siliconflow","volcengine-ark","bailian","moonshot","sensetime"]),_n=/@sailor:([^\s*]+)/;function Wa(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=>Sr.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 fr(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function yr(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function hr(e,t){let n=e.split(`
1757
+ `),o=[],r=e.includes("#"),s=0;for(;s<n.length;){let i=n[s],a=i.match(_n);if(!a){o.push(i),s++;continue}let{marker:c,keep:p}=Wa(a[1],t);if(c==="registry-entries"){o.push(r?yr(i):fr(i)),s++;continue}if(p){let d=r?yr(i):fr(i);d.trim().length>0&&o.push(d);let u=s+1;for(;u<n.length&&n[u].trim()!==""&&!_n.test(n[u]);)o.push(n[u]),u++;u<n.length&&n[u].trim()===""&&(o.push(n[u]),u++),s=u}else{let d=s+1;for(;d<n.length&&n[d].trim()!==""&&!_n.test(n[d]);)d++;d<n.length&&n[d].trim()===""&&d++,s=d}}return Xa(o.join(`
1758
+ `),t)}function Xa(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
1759
  `).filter(p=>{let d=p.trim();if(d===""||d.startsWith("//"))return!0;let u=d.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return u?r.has(u[1]):!0}).join(`
1760
- `);return e.replace(s,`createProviderRegistry({${c}})`)}function Xa(e,t){let n=it.join(t,"registry.ts.template"),o=we.readFileSync(n,"utf-8");return hr(o,e)}function za(e,t){let n=it.join(t,".env.example.template"),o=we.readFileSync(n,"utf-8");return hr(o,e)}async function Er(e,t,n){let o=Xa(t,n),r=za(t,n),s=it.join(e,"packages/ai/agents/src");await we.promises.mkdir(s,{recursive:!0}),await we.promises.writeFile(it.join(s,"registry.ts"),o),await we.promises.appendFile(it.join(e,".env.example"),`
1761
- `+r);let i={ai:"latest"},{providerIds:a,customEndpoint:c}=t;(a.includes("openai")||c||a.some(d=>Sr.has(d)))&&(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=it.join(e,"package.json");if(we.existsSync(p)){let d=JSON.parse(await we.promises.readFile(p,"utf-8"));d.dependencies||(d.dependencies={});for(let[u,A]of Object.entries(i))d.dependencies[u]=A;await we.promises.writeFile(p,JSON.stringify(d,null,2)+`
1760
+ `);return e.replace(s,`createProviderRegistry({${c}})`)}function za(e,t){let n=it.join(t,"registry.ts.template"),o=Pe.readFileSync(n,"utf-8");return hr(o,e)}function Ja(e,t){let n=it.join(t,".env.example.template"),o=Pe.readFileSync(n,"utf-8");return hr(o,e)}async function Er(e,t,n){let o=za(t,n),r=Ja(t,n),s=it.join(e,"packages/ai/agents/src");await Pe.promises.mkdir(s,{recursive:!0}),await Pe.promises.writeFile(it.join(s,"registry.ts"),o),await Pe.promises.appendFile(it.join(e,".env.example"),`
1761
+ `+r);let i={ai:"latest"},{providerIds:a,customEndpoint:c}=t;(a.includes("openai")||c||a.some(d=>Sr.has(d)))&&(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=it.join(e,"package.json");if(Pe.existsSync(p)){let d=JSON.parse(await Pe.promises.readFile(p,"utf-8"));d.dependencies||(d.dependencies={});for(let[u,A]of Object.entries(i))d.dependencies[u]=A;await Pe.promises.writeFile(p,JSON.stringify(d,null,2)+`
1762
1762
  `)}}import y from"fs";import f from"path";function vr(e,t){if(!y.existsSync(e))return;let n=y.readdirSync(e);for(let o of n){let r=f.join(e,o);y.statSync(r).isDirectory()?vr(r,t):t(r)}}async function br(e,t){let n=f.join(e,"package.json");if(!y.existsSync(n))return;let o=JSON.parse(y.readFileSync(n,"utf8"));if(t.orm!=="prisma"){let r=f.join(e,"packages","db");if(y.existsSync(r)){let s=f.join(r,"prisma");y.existsSync(s)&&y.rmSync(s,{recursive:!0,force:!0});let i=f.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
1763
  `)}let a=f.join(r,"src","index.ts");y.existsSync(a)&&y.writeFileSync(a,`
1764
1764
  export const prisma = {} as any;
@@ -1849,12 +1849,12 @@ export { default } from './mock-i18n';
1849
1849
  "next-intl": ["./src/lib/mock-i18n"],
1850
1850
  "next-intl/*": ["./src/lib/mock-i18n"],`);y.writeFileSync(h,m)}}catch{}let g=f.join(a,"src");y.existsSync(g)&&vr(g,S=>{if(!S.endsWith(".ts")&&!S.endsWith(".tsx"))return;let m=y.readFileSync(S,"utf8"),_=!1;S.endsWith("src/app/layout.tsx")&&m.includes("../providers")&&(m=m.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),_=!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"),_=!0),m.match(/lang\s*:\s*any/)&&(m=m.replace(/lang\s*:\s*any/g,"lang: string"),_=!0),m.match(/requestLocale\s*:\s*any/)&&(m=m.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),_=!0),m.match(/\(locale\s*=\s*(.*)\)/)&&(m=m.replace(/\(locale\s*=\s*(.*)\)/g,"() "),_=!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 })"),_=!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) =>"),_=!0),S.endsWith("src/i18n/request.ts")&&(m=m.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),_=!0),(m.match(/locale\s*:/)||m.match(/lang\s*:/))&&(_=!0),_&&y.writeFileSync(S,m)});let E=f.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 Ja(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 _r(e,t){t.cronJobs||(b(f.join(e,"apps/web/src/app/api/cron")),b(f.join(e,"packages/integrations/queue/src/scheduled"))),t.auditLog||(b(f.join(e,"apps/web/src/app/[locale]/(app)/settings/audit-log")),b(f.join(e,"apps/web/src/app/api/audit-logs")),b(f.join(e,"apps/web/src/components/audit"))),t.apiKeys||(b(f.join(e,"apps/web/src/app/[locale]/(app)/settings/api-keys")),b(f.join(e,"apps/web/src/app/api/api-keys")),b(f.join(e,"apps/web/src/components/api-keys"))),t.webhooks||(b(f.join(e,"apps/web/src/app/[locale]/(app)/settings/webhooks")),b(f.join(e,"apps/web/src/app/api/webhooks")),b(f.join(e,"apps/web/src/components/webhooks")),b(f.join(e,"packages/integrations/webhooks"))),t.commandPalette||(b(f.join(e,"apps/web/src/components/command-palette")),b(f.join(e,"apps/web/src/app/[locale]/providers/command-palette-mount.tsx"))),t.cookieConsent||(b(f.join(e,"apps/landing/src/components/cookie-consent-banner.tsx")),b(f.join(e,"apps/landing/src/components/__tests__/cookie-consent-banner.test.tsx")),b(f.join(e,"apps/landing/src/lib/cookie-consent.ts")),b(f.join(e,"apps/landing/src/lib/__tests__/cookie-consent.test.ts")),b(f.join(e,"apps/web/src/app/api/cookie-consent"))),t.legalPages||(b(f.join(e,"apps/landing/src/app/[lang]/(legal)/legal")),b(f.join(e,"apps/landing/src/lib/legal-documents.ts")),b(f.join(e,"apps/landing/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(b(f.join(e,"packages/ops/china-compliance")),b(f.join(e,"apps/landing/src/components/icp-footer.tsx")),b(f.join(e,"apps/landing/src/components/__tests__/icp-footer.test.tsx")),b(f.join(e,"apps/web/src/components/auth/wechat-login-button.tsx")),b(f.join(e,"apps/web/src/components/auth/__tests__/wechat-login-button.test.tsx")),Ja(f.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import at from"fs";import Pr from"path";var wr=/^--\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/m;function Qa(e){let t=wr.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 Za(e){return e.replace(wr,"").replace(/^\n/,"")}function Pn(e,t){let n={kept:[],removed:[],skipped:[]};if(!at.existsSync(e))return n;let o=at.readdirSync(e,{withFileTypes:!0}).filter(r=>r.isDirectory()).sort((r,s)=>r.name.localeCompare(s.name));for(let r of o){let s=Pr.join(e,r.name),i=Pr.join(s,"migration.sql");if(!at.existsSync(i)){n.skipped.push(r.name);continue}let a=at.readFileSync(i,"utf8"),c=Qa(a);if(!c){n.skipped.push(r.name);continue}let p=t[c.flag];if(p!==void 0&&c.values.includes(p)){at.writeFileSync(i,Za(a)),n.kept.push(r.name);continue}at.rmSync(s,{recursive:!0,force:!0}),n.removed.push(r.name)}return n}import{getSchema as ec,printSchema as tc}from"@mrleebo/prisma-ast";var nc=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function oc(e){return e.type==="comment"&&e.text.trim().startsWith("//")}function rc(e){let t=nc.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 sc(e,t){for(let n=t-1;n>=0;n--){let o=e[n];if(o.type==="comment"){let r=rc(o.text);if(r)return{annIndex:n,parsed:r};continue}break}return null}function ic(e){return e.type==="model"||e.type==="enum"}function wn(e,t){let n=ec(e),o=new Set;for(let a=0;a<n.list.length;a++){let c=n.list[a];if(!ic(c))continue;let p=sc(n.list,a);if(!p)continue;let d=t[p.parsed.flag];if(d!==void 0&&p.parsed.values.includes(d))o.add(p.annIndex);else{o.add(a);for(let h=a-1;h>=0;h--){let g=n.list[h];if(oc(g)){o.add(h);continue}break}let A=n.list[a+1];A&&A.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 tc({type:"schema",list:s})}import ct from"fs";import Cr from"path";var jt=[{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 Ar(e){return jt.find(t=>t.id===e)}var mu=jt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ir(e){return ct.existsSync(e)?ct.readFileSync(e,"utf-8"):null}function ac(e,t){let n=Cr.join(e,".env.example"),o=Ir(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
- `);ct.appendFileSync(n,s)}function cc(e,t,n){let o=Cr.join(e,".env.example"),r=Ir(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?ct.writeFileSync(o,r.replace(s,`${t}="${n}"`)):ct.appendFileSync(o,`${t}="${n}"
1855
- `)}async function xr(e,t,n){let o=Le(e,"queue");if(t==="none"){o&&ct.rmSync(o,{recursive:!0,force:!0});return}let r=Ar(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${jt.map(s=>s.id).join(", ")}`);o&&(ac(e,r),cc(e,"QUEUE_PROVIDER",t))}import fe from"fs";import Ae from"path";import{fileURLToPath as pc}from"url";var lc=pc(import.meta.url),Rr=Ae.dirname(lc),dc=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|toml|py)$/,uc=["backends/gateway","infra","e2e","tests"];function mc(){let e=[Ae.join(Rr,"..","templates"),Ae.join(Rr,"..","..","templates")];for(let t of e)if(fe.existsSync(t))return t;return e[0]}async function Tr(e,t){let n=mc(),o=[],r=[],s=[...uc,...t.withWorkflows?["workflows"]:[],...t.withPythonBackend?["backends/python"]:[]];for(let i of s){let a=Ae.join(n,i);if(!fe.existsSync(a)){r.push(i);continue}let c=Ae.join(e,i);kr(a,c),Nr(c,{"{PRODUCT_NAME}":t.projectName}),o.push(i)}return{applied:o,skipped:r}}function kr(e,t){fe.mkdirSync(t,{recursive:!0});for(let n of fe.readdirSync(e,{withFileTypes:!0})){let o=Ae.join(e,n.name),r=Ae.join(t,n.name);n.isDirectory()?kr(o,r):fe.existsSync(r)||fe.copyFileSync(o,r)}}function Nr(e,t){for(let n of fe.readdirSync(e,{withFileTypes:!0})){let o=Ae.join(e,n.name);if(n.isDirectory()){Nr(o,t);continue}if(!dc.test(n.name))continue;let r=fe.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&&fe.writeFileSync(o,r)}}import pt from"fs";import Lr from"path";var Bt=[{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 Or(e){return Bt.find(t=>t.id===e)}var wu=Bt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ur(e){return pt.existsSync(e)?pt.readFileSync(e,"utf-8"):null}function gc(e,t){let n=Lr.join(e,".env.example"),o=Ur(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
- `);pt.appendFileSync(n,s)}function fc(e,t,n){let o=Lr.join(e,".env.example"),r=Ur(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?pt.writeFileSync(o,r.replace(s,`${t}="${n}"`)):pt.appendFileSync(o,`${t}="${n}"
1857
- `)}async function Dr(e,t,n){let o=Le(e,"search");if(t==="none"){o&&pt.rmSync(o,{recursive:!0,force:!0});return}let r=Or(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${Bt.map(s=>s.id).join(", ")}`);o&&(gc(e,r),fc(e,"SEARCH_PROVIDER",t))}import Ce from"fs";import $e from"path";function yc(e){let t=[$e.join(e,"packages","db"),$e.join(e,"apps","web")];for(let n of t){let o=$e.join(n,"prisma","schema.prisma");if(Ce.existsSync(o))return{packageDir:n,seedPath:$e.join(n,"prisma","seed.ts"),packageJsonPath:$e.join(n,"package.json")}}return null}function Sc(e){try{let t=Ce.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 hc(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 Qa(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 _r(e,t){t.cronJobs||(b(f.join(e,"apps/web/src/app/api/cron")),b(f.join(e,"packages/integrations/queue/src/scheduled"))),t.auditLog||(b(f.join(e,"apps/web/src/app/[locale]/(app)/settings/audit-log")),b(f.join(e,"apps/web/src/app/api/audit-logs")),b(f.join(e,"apps/web/src/components/audit"))),t.apiKeys||(b(f.join(e,"apps/web/src/app/[locale]/(app)/settings/api-keys")),b(f.join(e,"apps/web/src/app/api/api-keys")),b(f.join(e,"apps/web/src/components/api-keys"))),t.webhooks||(b(f.join(e,"apps/web/src/app/[locale]/(app)/settings/webhooks")),b(f.join(e,"apps/web/src/app/api/webhooks")),b(f.join(e,"apps/web/src/components/webhooks")),b(f.join(e,"packages/integrations/webhooks"))),t.commandPalette||(b(f.join(e,"apps/web/src/components/command-palette")),b(f.join(e,"apps/web/src/app/[locale]/providers/command-palette-mount.tsx"))),t.cookieConsent||(b(f.join(e,"apps/landing/src/components/cookie-consent-banner.tsx")),b(f.join(e,"apps/landing/src/components/__tests__/cookie-consent-banner.test.tsx")),b(f.join(e,"apps/landing/src/lib/cookie-consent.ts")),b(f.join(e,"apps/landing/src/lib/__tests__/cookie-consent.test.ts")),b(f.join(e,"apps/web/src/app/api/cookie-consent"))),t.legalPages||(b(f.join(e,"apps/landing/src/app/[lang]/(legal)/legal")),b(f.join(e,"apps/landing/src/lib/legal-documents.ts")),b(f.join(e,"apps/landing/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(b(f.join(e,"packages/ops/china-compliance")),b(f.join(e,"apps/landing/src/components/icp-footer.tsx")),b(f.join(e,"apps/landing/src/components/__tests__/icp-footer.test.tsx")),b(f.join(e,"apps/web/src/components/auth/wechat-login-button.tsx")),b(f.join(e,"apps/web/src/components/auth/__tests__/wechat-login-button.test.tsx")),Qa(f.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import at from"fs";import wr from"path";var Pr=/^--\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/m;function Za(e){let t=Pr.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 ec(e){return e.replace(Pr,"").replace(/^\n/,"")}function wn(e,t){let n={kept:[],removed:[],skipped:[]};if(!at.existsSync(e))return n;let o=at.readdirSync(e,{withFileTypes:!0}).filter(r=>r.isDirectory()).sort((r,s)=>r.name.localeCompare(s.name));for(let r of o){let s=wr.join(e,r.name),i=wr.join(s,"migration.sql");if(!at.existsSync(i)){n.skipped.push(r.name);continue}let a=at.readFileSync(i,"utf8"),c=Za(a);if(!c){n.skipped.push(r.name);continue}let p=t[c.flag];if(p!==void 0&&c.values.includes(p)){at.writeFileSync(i,ec(a)),n.kept.push(r.name);continue}at.rmSync(s,{recursive:!0,force:!0}),n.removed.push(r.name)}return n}import{getSchema as tc,printSchema as nc}from"@mrleebo/prisma-ast";var oc=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function rc(e){return e.type==="comment"&&e.text.trim().startsWith("//")}function sc(e){let t=oc.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 ic(e,t){for(let n=t-1;n>=0;n--){let o=e[n];if(o.type==="comment"){let r=sc(o.text);if(r)return{annIndex:n,parsed:r};continue}break}return null}function ac(e){return e.type==="model"||e.type==="enum"}function Pn(e,t){let n=tc(e),o=new Set;for(let a=0;a<n.list.length;a++){let c=n.list[a];if(!ac(c))continue;let p=ic(n.list,a);if(!p)continue;let d=t[p.parsed.flag];if(d!==void 0&&p.parsed.values.includes(d))o.add(p.annIndex);else{o.add(a);for(let h=a-1;h>=0;h--){let g=n.list[h];if(rc(g)){o.add(h);continue}break}let A=n.list[a+1];A&&A.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 nc({type:"schema",list:s})}import ct from"fs";import Cr from"path";var jt=[{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 Ar(e){return jt.find(t=>t.id===e)}var fu=jt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ir(e){return ct.existsSync(e)?ct.readFileSync(e,"utf-8"):null}function cc(e,t){let n=Cr.join(e,".env.example"),o=Ir(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
+ `);ct.appendFileSync(n,s)}function pc(e,t,n){let o=Cr.join(e,".env.example"),r=Ir(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?ct.writeFileSync(o,r.replace(s,`${t}="${n}"`)):ct.appendFileSync(o,`${t}="${n}"
1855
+ `)}async function xr(e,t,n){let o=Le(e,"queue");if(t==="none"){o&&ct.rmSync(o,{recursive:!0,force:!0});return}let r=Ar(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${jt.map(s=>s.id).join(", ")}`);o&&(cc(e,r),pc(e,"QUEUE_PROVIDER",t))}import fe from"fs";import Ae from"path";import{fileURLToPath as lc}from"url";var dc=lc(import.meta.url),Rr=Ae.dirname(dc),uc=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|toml|py)$/,mc=["backends/gateway","infra","e2e","tests"];function gc(){let e=[Ae.join(Rr,"..","templates"),Ae.join(Rr,"..","..","templates")];for(let t of e)if(fe.existsSync(t))return t;return e[0]}async function Tr(e,t){let n=gc(),o=[],r=[],s=[...mc,...t.withWorkflows?["workflows"]:[],...t.withPythonBackend?["backends/python"]:[]];for(let i of s){let a=Ae.join(n,i);if(!fe.existsSync(a)){r.push(i);continue}let c=Ae.join(e,i);kr(a,c),Nr(c,{"{PRODUCT_NAME}":t.projectName}),o.push(i)}return{applied:o,skipped:r}}function kr(e,t){fe.mkdirSync(t,{recursive:!0});for(let n of fe.readdirSync(e,{withFileTypes:!0})){let o=Ae.join(e,n.name),r=Ae.join(t,n.name);n.isDirectory()?kr(o,r):fe.existsSync(r)||fe.copyFileSync(o,r)}}function Nr(e,t){for(let n of fe.readdirSync(e,{withFileTypes:!0})){let o=Ae.join(e,n.name);if(n.isDirectory()){Nr(o,t);continue}if(!uc.test(n.name))continue;let r=fe.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&&fe.writeFileSync(o,r)}}import pt from"fs";import Lr from"path";var Bt=[{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 Or(e){return Bt.find(t=>t.id===e)}var Cu=Bt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ur(e){return pt.existsSync(e)?pt.readFileSync(e,"utf-8"):null}function fc(e,t){let n=Lr.join(e,".env.example"),o=Ur(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
+ `);pt.appendFileSync(n,s)}function yc(e,t,n){let o=Lr.join(e,".env.example"),r=Ur(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?pt.writeFileSync(o,r.replace(s,`${t}="${n}"`)):pt.appendFileSync(o,`${t}="${n}"
1857
+ `)}async function Dr(e,t,n){let o=Le(e,"search");if(t==="none"){o&&pt.rmSync(o,{recursive:!0,force:!0});return}let r=Or(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${Bt.map(s=>s.id).join(", ")}`);o&&(fc(e,r),yc(e,"SEARCH_PROVIDER",t))}import Ce from"fs";import Ve from"path";function Sc(e){let t=[Ve.join(e,"packages","db"),Ve.join(e,"apps","web")];for(let n of t){let o=Ve.join(n,"prisma","schema.prisma");if(Ce.existsSync(o))return{packageDir:n,seedPath:Ve.join(n,"prisma","seed.ts"),packageJsonPath:Ve.join(n,"package.json")}}return null}function hc(e){try{let t=Ce.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 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=hc(e,o),i=n?` let tenants: Array<{ id: string; name: string }> = [];
1888
+ }`}function vc(e,t){let n=t.has("Tenant"),o=t.has("User"),r=t.has("Project"),s=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({
@@ -1954,12 +1954,12 @@ main()
1954
1954
  .finally(async () => {
1955
1955
  await prisma.$disconnect();
1956
1956
  });
1957
- `}function vc(e){if(Ce.existsSync(e))try{let t=Ce.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};Ce.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 Mr(e,t){let n=yc(e);if(n)try{let o=$e.join(n.packageDir,"prisma","schema.prisma"),r=Sc(o),s=Ec(t,r),i=$e.dirname(n.seedPath);Ce.existsSync(i)||Ce.mkdirSync(i,{recursive:!0}),Ce.writeFileSync(n.seedPath,s),vc(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 Ie from"fs";import Ke from"path";var Vt=[{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:""}],Lu=Vt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Fr(e){return Vt.find(t=>t.id===e)}var bc="@nebutra/sms",_c={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 An(e,t){Ie.mkdirSync(Ke.dirname(e),{recursive:!0}),Ie.writeFileSync(e,t)}function Pc(e,t){let n=Ke.join(e,".env.example");Ie.existsSync(n)?Ie.appendFileSync(n,`
1959
- `+t):Ie.writeFileSync(n,t)}function wc(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
1957
+ `}function bc(e){if(Ce.existsSync(e))try{let t=Ce.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};Ce.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 Mr(e,t){let n=Sc(e);if(n)try{let o=Ve.join(n.packageDir,"prisma","schema.prisma"),r=hc(o),s=vc(t,r),i=Ve.dirname(n.seedPath);Ce.existsSync(i)||Ce.mkdirSync(i,{recursive:!0}),Ce.writeFileSync(n.seedPath,s),bc(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 Ie from"fs";import Ke from"path";var $t=[{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=$t.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Fr(e){return $t.find(t=>t.id===e)}var _c="@nebutra/sms",wc={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 An(e,t){Ie.mkdirSync(Ke.dirname(e),{recursive:!0}),Ie.writeFileSync(e,t)}function Pc(e,t){let n=Ke.join(e,".env.example");Ie.existsSync(n)?Ie.appendFileSync(n,`
1959
+ `+t):Ie.writeFileSync(n,t)}function Ac(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 Ac=`/**
1962
+ `}var Cc=`/**
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 Cc(){return`import twilio from "twilio";
1982
+ `;function Ic(){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 Ic(){return`import messagebird from "messagebird";
2017
+ `}function xc(){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 xc(){return`import plivo from "plivo";
2055
+ `}function Rc(){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 Rc(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2094
+ `}function Tc(){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 Tc(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2143
+ `}function kc(){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 kc(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2208
+ `}function Nc(){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 Nc(e){switch(e){case"twilio":return Cc();case"messagebird":return Ic();case"plivo":return xc();case"aliyun-sms":return Rc();case"tencent-sms":return Tc();case"yunpian":return kc();case"none":return`export {};
2261
- `}}function Oc(e){let t={};for(let o of e.pkgs??[]){let r=_c[o];r&&(t[o]=r)}let n={name:bc,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 jr(e,t,n="global"){if(t==="none")return;let o=Fr(t);if(!o)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${Vt.map(i=>i.id).join(", ")}`);let r=Ke.join(e,"packages","sms");if(!Ie.existsSync(r))return;let s=Ke.join(r,"src");Ie.existsSync(s)&&Ie.rmSync(s,{recursive:!0,force:!0});try{An(Ke.join(r,"package.json"),Oc(o)),An(Ke.join(s,"types.ts"),Ac),An(Ke.join(s,"index.ts"),Nc(o.id)),Pc(e,wc(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 qe from"fs";import Ye from"path";var Ge="@nebutra/storage";function Cn(e,t){qe.mkdirSync(Ye.dirname(e),{recursive:!0}),qe.writeFileSync(e,t)}function Lc(e,t){let n=Ye.join(e,".env.example");qe.existsSync(n)?qe.appendFileSync(n,`
2263
- `+t):qe.writeFileSync(n,t)}function Uc(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
2260
+ `}function Oc(e){switch(e){case"twilio":return Ic();case"messagebird":return xc();case"plivo":return Rc();case"aliyun-sms":return Tc();case"tencent-sms":return kc();case"yunpian":return Nc();case"none":return`export {};
2261
+ `}}function Lc(e){let t={};for(let o of e.pkgs??[]){let r=wc[o];r&&(t[o]=r)}let n={name:_c,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 jr(e,t,n="global"){if(t==="none")return;let o=Fr(t);if(!o)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${$t.map(i=>i.id).join(", ")}`);let r=Ke.join(e,"packages","sms");if(!Ie.existsSync(r))return;let s=Ke.join(r,"src");Ie.existsSync(s)&&Ie.rmSync(s,{recursive:!0,force:!0});try{An(Ke.join(r,"package.json"),Lc(o)),An(Ke.join(s,"types.ts"),Cc),An(Ke.join(s,"index.ts"),Oc(o.id)),Pc(e,Ac(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 qe from"fs";import Ye from"path";var Ge="@nebutra/storage";function Cn(e,t){qe.mkdirSync(Ye.dirname(e),{recursive:!0}),qe.writeFileSync(e,t)}function Uc(e,t){let n=Ye.join(e,".env.example");qe.existsSync(n)?qe.appendFileSync(n,`
2263
+ `+t):qe.writeFileSync(n,t)}function Dc(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 Dc=`/**
2266
+ `}var Mc=`/**
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 Mc(){return`/**
2292
+ `;function Fc(){return`/**
2293
2293
  * @${Ge.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 Fc(){return`/**
2356
+ `}function jc(){return`/**
2357
2357
  * @${Ge.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 jc(){return`/**
2421
+ `}function Bc(){return`/**
2422
2422
  * @${Ge.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
  * @${Ge.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2486
2486
  *
2487
2487
  * Docs: https://help.aliyun.com/product/31815.html
@@ -2583,7 +2583,7 @@ export async function getSignedUrl(
2583
2583
  }
2584
2584
 
2585
2585
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2586
- `}function $c(){return`/**
2586
+ `}function Kc(){return`/**
2587
2587
  * @${Ge.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2588
2588
  *
2589
2589
  * Docs: https://developer.qiniu.com/kodo
@@ -2651,10 +2651,9 @@ export async function getSignedUrl(
2651
2651
  }
2652
2652
 
2653
2653
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2654
- `}function Kc(e){switch(e){case"r2":return Mc();case"s3":return Fc();case"supabase-storage":return jc();case"aliyun-oss":return Bc();case"tencent-cos":return Vc();case"qiniu":return $c();case"none":return`export {};
2655
- `}}function Yc(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:Ge,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 Br(e,t,n){if(t==="none")return;let o=$n(t);if(!o)throw new Error(`Unknown storage provider "${t}". Valid ids: ${Re.map(i=>i.id).join(", ")}`);let r=Ye.join(e,"packages","storage"),s=Ye.join(r,"src");qe.existsSync(s)&&qe.rmSync(s,{recursive:!0,force:!0}),Cn(Ye.join(r,"package.json"),Yc(o)),Cn(Ye.join(s,"types.ts"),Dc),Cn(Ye.join(s,"index.ts"),Kc(o.id)),Lc(e,Uc(o))}var $t=[{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 Vr(e){return $t.find(t=>t.id===e)}var Yu=$t.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function $r(e,t,n="global"){let o=Vr(t);if(!o)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${$t.map(r=>r.id).join(", ")}`);if(o.id==="none"){J(e,"webhooks");return}o.envVars.length>0&&re(e,{category:"Webhooks",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"WEBHOOKS_PROVIDER",o.id)}import He from"fs";import Pt from"path";function qc(e){return`import { brand } from "@nebutra/brand/metadata";
2657
- import Link from "next/link";
2654
+ `}function Yc(e){switch(e){case"r2":return Fc();case"s3":return jc();case"supabase-storage":return Bc();case"aliyun-oss":return $c();case"tencent-cos":return Vc();case"qiniu":return Kc();case"none":return`export {};
2655
+ `}}function qc(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:Ge,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 Br(e,t,n){if(t==="none")return;let o=$n(t);if(!o)throw new Error(`Unknown storage provider "${t}". Valid ids: ${Re.map(i=>i.id).join(", ")}`);let r=Ye.join(e,"packages","storage"),s=Ye.join(r,"src");qe.existsSync(s)&&qe.rmSync(s,{recursive:!0,force:!0}),Cn(Ye.join(r,"package.json"),qc(o)),Cn(Ye.join(s,"types.ts"),Mc),Cn(Ye.join(s,"index.ts"),Yc(o.id)),Uc(e,Dc(o))}var Vt=[{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 $r(e){return Vt.find(t=>t.id===e)}var Gu=Vt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Vr(e,t,n="global"){let o=$r(t);if(!o)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Vt.map(r=>r.id).join(", ")}`);if(o.id==="none"){J(e,"webhooks");return}o.envVars.length>0&&re(e,{category:"Webhooks",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"WEBHOOKS_PROVIDER",o.id)}import He from"fs";import wt from"path";function Gc(e){return`import Link from "next/link";
2658
2657
 
2659
2658
  export default function WelcomePage() {
2660
2659
  const projectName = ${JSON.stringify(e)};
@@ -2719,10 +2718,10 @@ export default function WelcomePage() {
2719
2718
  </li>
2720
2719
  <li>
2721
2720
  <a
2722
- href={\`https://\${brand.domains.landing}/get-license\`}
2721
+ href="https://nebutra.com/licensing"
2723
2722
  className="underline"
2724
2723
  >
2725
- Get free license (Individual/OPC)
2724
+ Licensing
2726
2725
  </a>
2727
2726
  </li>
2728
2727
  </ul>
@@ -2763,12 +2762,12 @@ function Step({
2763
2762
  </li>
2764
2763
  );
2765
2764
  }
2766
- `}function Gc(e={}){return`
2765
+ `}function Hc(e={}){return`
2767
2766
  ## What you can do next
2768
2767
 
2769
2768
  ${[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
2769
  `)}
2771
- `}function Hc(e=[]){return e.length===0?"":`
2770
+ `}function Wc(e=[]){return e.length===0?"":`
2772
2771
  ## Production readiness holds
2773
2772
 
2774
2773
  Do not enable these in production until provider credentials, adapter wiring, and the integration contract are verified:
@@ -2777,7 +2776,7 @@ ${e.map(n=>{let o=et(n.status);return`- ${n.flag}=${n.provider} ${o} \u2014 ${Te
2777
2776
  `)}
2778
2777
 
2779
2778
  Review the package readiness matrix before handoff: [docs/package-status.md](docs/package-status.md)
2780
- `}function Wc(e,t,n=[],o={}){return`# Next steps \u2014 ${e}
2779
+ `}function Xc(e,t,n=[],o={}){return`# Next steps \u2014 ${e}
2781
2780
 
2782
2781
  Region: ${t}
2783
2782
 
@@ -2803,28 +2802,28 @@ Your AI-native SaaS scaffold is ready. Complete these four steps to go from temp
2803
2802
  \`\`\`
2804
2803
 
2805
2804
  After setup, delete the welcome route at \`apps/web/src/app/[locale]/welcome/\`.
2806
- ${Gc(o)}${Hc(n)}
2805
+ ${Hc(o)}${Wc(n)}
2807
2806
 
2808
2807
  ## Resources
2809
2808
 
2810
2809
  - [Documentation](/docs)
2811
2810
  - [GitHub](https://github.com/nebutra/nebutra-sailor)
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=Pt.join(e,".sailor");He.existsSync(i)||He.mkdirSync(i,{recursive:!0}),He.writeFileSync(Pt.join(i,"next-steps.md"),Wc(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=Pt.join(e,"apps","web");if(!He.existsSync(i))return;let a=Pt.join(i,"src","app","[locale]","welcome");He.existsSync(a)||He.mkdirSync(a,{recursive:!0}),He.writeFileSync(Pt.join(a,"page.tsx"),qc(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 Yr(e){return e!==null&&typeof e=="object"&&"code"in e&&e.code==="ENOENT"}function zc(e,t){for(let n of t)if(e)l(!0,{event:"warn",step:n.flag,provider:n.provider,packageStatus:n.status,message:Te(n.status)});else{let o=et(n.status);process.stdout.write(We.yellow(`\u26A0 ${n.flag}=${n.provider} ${o} \u2014 ${Te(n.status)}
2815
- `))}}function Jc(e,t,n){let o=Xe.join(t,"packages/platform/db/prisma/schema.prisma"),r;try{r=Yt.readFileSync(o,"utf8")}catch(s){if(Yr(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=wn(r,n);Yt.writeFileSync(o,s),Pn(Xe.join(Xe.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 qr(e){let{resolvedTarget:t,projectName:n,resolvedPm:o,opts:r,useJson:s,resolved:i,startedAt:a}=e,{region:c,orm:p,database:d,databaseHost:u,payment:A,paymentChoice:h,auth:g,socialLoginIds:E,aiProviders:S,deployTarget:m,docs:_,metering:H,billingMode:M,idp:he,accessGate:le,mcp:ee,waveToggles:$,previewSelections:K,config:C}=i,W={auth:g,payment:h,"billing-mode":M,idp:he,template:"saas","access-gate":le};l(s,{event:"step",step:"clone",status:"start"}),await Wo(t),l(s,{event:"step",step:"clone",status:"ok"}),l(s,{event:"step",step:"package",status:"start"}),await pr(t,n),l(s,{event:"step",step:"package",status:"ok"}),l(s,{event:"step",step:"config",status:"start"}),await _o(t,C),l(s,{event:"step",step:"config",status:"ok"}),l(s,{event:"step",step:"governance-lints",status:"start"});let de=await zo(t,C);l(s,{event:"step",step:"governance-lints",status:"ok",lints:de.lints}),l(s,{event:"step",step:"prune",status:"start"}),await br(t,C),l(s,{event:"step",step:"prune",status:"ok"});{let v=Xe.join(t,"packages/platform/db/prisma/schema.prisma"),R;try{R=Yt.readFileSync(v,"utf-8")}catch(w){if(Yr(w))l(s,{event:"step",step:"schema-prune",status:"skip"});else{let I=w instanceof Error?w.message:String(w);l(s,{event:"step",step:"schema-prune",status:"error",error:I})}}if(R!==void 0){l(s,{event:"step",step:"schema-prune",status:"start"});try{let w=wn(R,W);Yt.writeFileSync(v,w),Pn(Xe.join(Xe.dirname(v),"migrations"),W),l(s,{event:"step",step:"schema-prune",status:"ok"})}catch(w){let I=w instanceof Error?w.message:String(w);l(s,{event:"step",step:"schema-prune",status:"error",error:I})}}}if(l(s,{event:"step",step:"auth",choice:g,status:"start"}),await po(t,g),l(s,{event:"step",step:"auth",choice:g,status:"ok"}),E.length>0?(l(s,{event:"step",step:"social-login",providers:E,status:"start"}),await uo(t,E,g),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:d,status:"start"}),await Ao(t,d,n),d!=="none"){let v=mt(u);v&&(await Co(t,v,n),l(s,{event:"step",step:"db-host",choice:u,status:"ok"}))}if(l(s,{event:"step",step:"db",choice:d,status:"ok"}),p==="drizzle"){l(s,{event:"step",step:"orm",choice:"drizzle",status:"start"});let v=await ur(t,"drizzle",d);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 gr(t,h),l(s,{event:"step",step:"payment",choice:h,status:"ok"}),await Oo(t,i.email,c),s&&l(!0,{event:"step",step:"email",choice:i.email,status:"ok"}),await Br(t,i.storage,c),s&&l(!0,{event:"step",step:"storage",choice:i.storage,status:"ok"}),await ir(t,i.monitoring,c),s&&l(!0,{event:"step",step:"monitoring",choice:i.monitoring,status:"ok"}),await ao(t,i.analytics,c),s&&l(!0,{event:"step",step:"analytics",choice:i.analytics,status:"ok"}),await jr(t,i.sms,c),s&&l(!0,{event:"step",step:"sms",choice:i.sms,status:"ok"}),await xr(t,i.queue,c),s&&l(!0,{event:"step",step:"queue",choice:i.queue,status:"ok"}),await Dr(t,i.search,c),s&&l(!0,{event:"step",step:"search",choice:i.search,status:"ok"}),await yo(t,i.cache,c),s&&l(!0,{event:"step",step:"cache",choice:i.cache,status:"ok"}),await cr(t,i.notifications,c),s&&l(!0,{event:"step",step:"notifications",choice:i.notifications,status:"ok"}),await $r(t,i.webhooks,c),s&&l(!0,{event:"step",step:"webhooks",choice:i.webhooks,status:"ok"}),await vo(t,i.cms,c),s&&l(!0,{event:"step",step:"cms",choice:i.cms,status:"ok"}),await Vo(t,i.featureFlags,c),s&&l(!0,{event:"step",step:"feature-flags",choice:i.featureFlags,status:"ok"}),await ho(t,i.captcha,c),s&&l(!0,{event:"step",step:"captcha",choice:i.captcha,status:"ok"}),await tr(t,ee),s&&l(!0,{event:"step",step:"mcp",mode:ee,status:"ok"}),await or(t,H,A),s&&l(!0,{event:"step",step:"metering",mode:H,status:"ok"}),l(s,{event:"step",step:"prune-wave-features",status:"start"}),_r(t,$),l(s,{event:"step",step:"prune-wave-features",status:"ok",toggles:$}),C.orm==="prisma"&&C.database!=="none"?Jc(s,t,W):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:he,status:"ok"}),await bo(t,c),s&&l(!0,{event:"step",step:"compliance",region:c,status:"ok"}),await jo(t),await Mr(t,g),await Kr(t,{projectName:n,region:c,previewSelections:K,waveFeatures:$}),C.aiMode!=="none"){l(s,{event:"step",step:"ai-providers",status:"start"});let v={providerIds:C.aiProviders,customEndpoint:C.customAiEndpoint},R=Xe.join(t,"packages/ai/ai-providers/templates");await Er(t,v,R),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"}),_!=="none"?(await Ro(t,{framework:_,projectName:n}),l(s,{event:"step",step:"docs",framework:"fumadocs",requested:_,status:"ok"})):l(s,{event:"step",step:"docs",status:"skip"}),l(s,{event:"step",step:"deploy-target",status:"start"}),m!=="none"&&await to(t,m),await eo(t,C.deployTargets),l(s,{event:"step",step:"deploy-target",status:"ok",targets:C.deployTargets});let P={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""};l(s,{event:"step",step:"env",status:"start"}),await Do(t,P),l(s,{event:"step",step:"env",status:"ok"}),l(s,{event:"step",step:"scaffold-extras",status:"start"});let Ee=await Tr(t,{projectName:n,withWorkflows:!!r.withWorkflows,withPythonBackend:!!r.withPythonBackend});l(s,{event:"step",step:"scaffold-extras",status:"ok",applied:Ee.applied,skipped:Ee.skipped}),l(s,{event:"step",step:"license",status:"start"});try{let v=er(t,{projectName:n,cliVersion:z});l(s,{event:"step",step:"license",status:"ok",tier:"mit-scaffold",wrote:v.wrote}),s||process.stdout.write(We.dim(` License: MIT \u2014 commercial use, closed source, no fee, no attribution.
2811
+ - [Licensing](https://nebutra.com/licensing)
2812
+ `}async function Kr(e,t){let{projectName:n,region:o,previewSelections:r=[],waveFeatures:s={}}=t;try{let i=wt.join(e,".sailor");He.existsSync(i)||He.mkdirSync(i,{recursive:!0}),He.writeFileSync(wt.join(i,"next-steps.md"),Xc(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=wt.join(e,"apps","web");if(!He.existsSync(i))return;let a=wt.join(i,"src","app","[locale]","welcome");He.existsSync(a)||He.mkdirSync(a,{recursive:!0}),He.writeFileSync(wt.join(a,"page.tsx"),Gc(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)+`
2813
+ `)}function Yr(e){return e!==null&&typeof e=="object"&&"code"in e&&e.code==="ENOENT"}function Jc(e,t){for(let n of t)if(e)l(!0,{event:"warn",step:n.flag,provider:n.provider,packageStatus:n.status,message:Te(n.status)});else{let o=et(n.status);process.stdout.write(We.yellow(`\u26A0 ${n.flag}=${n.provider} ${o} \u2014 ${Te(n.status)}
2814
+ `))}}function Qc(e,t,n){let o=Xe.join(t,"packages/platform/db/prisma/schema.prisma"),r;try{r=Yt.readFileSync(o,"utf8")}catch(s){if(Yr(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=Pn(r,n);Yt.writeFileSync(o,s),wn(Xe.join(Xe.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 qr(e){let{resolvedTarget:t,projectName:n,resolvedPm:o,opts:r,useJson:s,resolved:i,startedAt:a}=e,{region:c,orm:p,database:d,databaseHost:u,payment:A,paymentChoice:h,auth:g,socialLoginIds:E,aiProviders:S,deployTarget:m,docs:_,metering:H,billingMode:M,idp:he,accessGate:le,mcp:ee,waveToggles:V,previewSelections:K,config:C}=i,W={auth:g,payment:h,"billing-mode":M,idp:he,template:"saas","access-gate":le};l(s,{event:"step",step:"clone",status:"start"}),await Wo(t),l(s,{event:"step",step:"clone",status:"ok"}),l(s,{event:"step",step:"package",status:"start"}),await pr(t,n),l(s,{event:"step",step:"package",status:"ok"}),l(s,{event:"step",step:"config",status:"start"}),await _o(t,C),l(s,{event:"step",step:"config",status:"ok"}),l(s,{event:"step",step:"governance-lints",status:"start"});let de=await zo(t,C);l(s,{event:"step",step:"governance-lints",status:"ok",lints:de.lints}),l(s,{event:"step",step:"prune",status:"start"}),await br(t,C),l(s,{event:"step",step:"prune",status:"ok"});{let v=Xe.join(t,"packages/platform/db/prisma/schema.prisma"),R;try{R=Yt.readFileSync(v,"utf-8")}catch(P){if(Yr(P))l(s,{event:"step",step:"schema-prune",status:"skip"});else{let I=P instanceof Error?P.message:String(P);l(s,{event:"step",step:"schema-prune",status:"error",error:I})}}if(R!==void 0){l(s,{event:"step",step:"schema-prune",status:"start"});try{let P=Pn(R,W);Yt.writeFileSync(v,P),wn(Xe.join(Xe.dirname(v),"migrations"),W),l(s,{event:"step",step:"schema-prune",status:"ok"})}catch(P){let I=P instanceof Error?P.message:String(P);l(s,{event:"step",step:"schema-prune",status:"error",error:I})}}}if(l(s,{event:"step",step:"auth",choice:g,status:"start"}),await po(t,g),l(s,{event:"step",step:"auth",choice:g,status:"ok"}),E.length>0?(l(s,{event:"step",step:"social-login",providers:E,status:"start"}),await uo(t,E,g),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:d,status:"start"}),await Ao(t,d,n),d!=="none"){let v=mt(u);v&&(await Co(t,v,n),l(s,{event:"step",step:"db-host",choice:u,status:"ok"}))}if(l(s,{event:"step",step:"db",choice:d,status:"ok"}),p==="drizzle"){l(s,{event:"step",step:"orm",choice:"drizzle",status:"start"});let v=await ur(t,"drizzle",d);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 gr(t,h),l(s,{event:"step",step:"payment",choice:h,status:"ok"}),await Oo(t,i.email,c),s&&l(!0,{event:"step",step:"email",choice:i.email,status:"ok"}),await Br(t,i.storage,c),s&&l(!0,{event:"step",step:"storage",choice:i.storage,status:"ok"}),await ir(t,i.monitoring,c),s&&l(!0,{event:"step",step:"monitoring",choice:i.monitoring,status:"ok"}),await io(t,i.analytics,c),s&&l(!0,{event:"step",step:"analytics",choice:i.analytics,status:"ok"}),await jr(t,i.sms,c),s&&l(!0,{event:"step",step:"sms",choice:i.sms,status:"ok"}),await xr(t,i.queue,c),s&&l(!0,{event:"step",step:"queue",choice:i.queue,status:"ok"}),await Dr(t,i.search,c),s&&l(!0,{event:"step",step:"search",choice:i.search,status:"ok"}),await yo(t,i.cache,c),s&&l(!0,{event:"step",step:"cache",choice:i.cache,status:"ok"}),await cr(t,i.notifications,c),s&&l(!0,{event:"step",step:"notifications",choice:i.notifications,status:"ok"}),await Vr(t,i.webhooks,c),s&&l(!0,{event:"step",step:"webhooks",choice:i.webhooks,status:"ok"}),await vo(t,i.cms,c),s&&l(!0,{event:"step",step:"cms",choice:i.cms,status:"ok"}),await $o(t,i.featureFlags,c),s&&l(!0,{event:"step",step:"feature-flags",choice:i.featureFlags,status:"ok"}),await ho(t,i.captcha,c),s&&l(!0,{event:"step",step:"captcha",choice:i.captcha,status:"ok"}),await tr(t,ee),s&&l(!0,{event:"step",step:"mcp",mode:ee,status:"ok"}),await or(t,H,A),s&&l(!0,{event:"step",step:"metering",mode:H,status:"ok"}),l(s,{event:"step",step:"prune-wave-features",status:"start"}),_r(t,V),l(s,{event:"step",step:"prune-wave-features",status:"ok",toggles:V}),C.orm==="prisma"&&C.database!=="none"?Qc(s,t,W):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:he,status:"ok"}),await bo(t,c),s&&l(!0,{event:"step",step:"compliance",region:c,status:"ok"}),await jo(t),await Mr(t,g),await Kr(t,{projectName:n,region:c,previewSelections:K,waveFeatures:V}),C.aiMode!=="none"){l(s,{event:"step",step:"ai-providers",status:"start"});let v={providerIds:C.aiProviders,customEndpoint:C.customAiEndpoint},R=Xe.join(t,"packages/ai/ai-providers/templates");await Er(t,v,R),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"}),_!=="none"?(await Ro(t,{framework:_,projectName:n}),l(s,{event:"step",step:"docs",framework:"fumadocs",requested:_,status:"ok"})):l(s,{event:"step",step:"docs",status:"skip"}),l(s,{event:"step",step:"deploy-target",status:"start"}),m!=="none"&&await eo(t,m),await Zn(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 Do(t,w),l(s,{event:"step",step:"env",status:"ok"}),l(s,{event:"step",step:"scaffold-extras",status:"start"});let Ee=await Tr(t,{projectName:n,withWorkflows:!!r.withWorkflows,withPythonBackend:!!r.withPythonBackend});l(s,{event:"step",step:"scaffold-extras",status:"ok",applied:Ee.applied,skipped:Ee.skipped}),l(s,{event:"step",step:"license",status:"start"});try{let v=er(t,{projectName:n,cliVersion:z});l(s,{event:"step",step:"license",status:"ok",tier:"mit-scaffold",wrote:v.wrote}),s||process.stdout.write(We.dim(` License: MIT \u2014 commercial use, closed source, no fee, no attribution.
2816
2815
  Upstream terms preserved as LICENSE-UPSTREAM-REFERENCE.md.
2817
2816
  `))}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,R=["install"];s?l(!0,{event:"step",step:"install",pm:o,status:"start"}):process.stdout.write(We.dim(` Installing dependencies with ${o}\u2026
2818
2817
  `));try{Kt(v,R,{cwd:t,stdio:s?"ignore":"inherit"}),l(s,{event:"step",step:"install",status:"ok"}),s||process.stdout.write(We.green(` \u2713 Dependencies installed (${o})
2819
- `))}catch(w){let I=w instanceof Error?w.message:String(w);s?l(!0,{event:"step",step:"install",status:"error",error:I}):process.stdout.write(We.yellow(`
2818
+ `))}catch(P){let I=P instanceof Error?P.message:String(P);s?l(!0,{event:"step",step:"install",status:"error",error:I}):process.stdout.write(We.yellow(`
2820
2819
  \u26A0 Install failed \u2014 the project files are ready, but deps are incomplete.
2821
2820
  Fix: ${We.cyan(`cd ${t} && ${o} install`)}
2822
2821
 
2823
2822
  `))}}else l(s,{event:"step",step:"install",status:"skip"});if(r.git!==!1){s&&l(!0,{event:"step",step:"git-init",status:"start"});try{Kt("git",["init","-q"],{cwd:t,stdio:"ignore"}),Kt("git",["add","-A"],{cwd:t,stdio:"ignore"}),Kt("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 R=v instanceof Error?v.message:String(v);s?l(!0,{event:"step",step:"git-init",status:"error",error:R}):process.stdout.write(We.yellow(` \u26A0 git init skipped \u2014 not fatal.
2824
- `))}}else l(s,{event:"step",step:"git-init",status:"skip"});let ve=Math.max(1,Math.round((Date.now()-a)/1e3));co({template_version:z,package_manager:o,region:c,auth:g,payment:h,ai_providers:S,deploy_target:m,duration_ms:Date.now()-a}),K.length>0&&zc(s,K),s?l(!0,{event:"done",status:"ok",elapsedSec:ve,targetDir:t,previewSelections:K,waveFeatures:$}):ro({elapsedSec:ve,targetDir:t,packageManager:o,skippedInstall:r.install===!1,hasDatabase:d!=="none",previewSelections:K});try{Xc({pkg:{name:"create-sailor",version:z},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}}import Qc from"cfonts";import Zc from"picocolors";function Gr(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${z}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
2825
- `));return}Qc.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(Zc.dim(` AI-Native SaaS Template \xB7 v${z} \xB7 nebutra.com
2823
+ `))}}else l(s,{event:"step",step:"git-init",status:"skip"});let ve=Math.max(1,Math.round((Date.now()-a)/1e3));co({template_version:z,package_manager:o,region:c,auth:g,payment:h,ai_providers:S,deploy_target:m,duration_ms:Date.now()-a}),K.length>0&&Jc(s,K),s?l(!0,{event:"done",status:"ok",elapsedSec:ve,targetDir:t,previewSelections:K,waveFeatures:V}):oo({elapsedSec:ve,targetDir:t,packageManager:o,skippedInstall:r.install===!1,hasDatabase:d!=="none",previewSelections:K});try{zc({pkg:{name:"create-sailor",version:z},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}}import Zc from"cfonts";import ep from"picocolors";function Gr(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${z}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
2824
+ `));return}Zc.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(ep.dim(` AI-Native SaaS Template \xB7 v${z} \xB7 nebutra.com
2826
2825
 
2827
- `))}var ep=`Usage: create-sailor [name] [options]
2826
+ `))}var tp=`Usage: create-sailor [name] [options]
2828
2827
 
2829
2828
  Arguments:
2830
2829
  name project name or path (default: my-app; use . for cwd)
@@ -2904,19 +2903,19 @@ Examples:
2904
2903
  $ npx create-sailor@latest my-app --region=cn --auth=clerk
2905
2904
  $ npx create-sailor@latest my-app --region=hybrid --ai=openai,deepseek
2906
2905
  $ npx create-sailor@latest my-app --dry-run --region=cn
2907
- `;function Hr(){process.stdout.write(ep)}import qt from"picocolors";function Wr(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function tp(e){let t=Wr()?"\u25B8":"->",n=`[${e.index}/${e.total}]`,o=e.label.padEnd(18," ");return Wr()?`${qt.dim(n)} ${qt.bold(o)} ${qt.dim(t)} ${qt.cyan(e.value)}`:`${n} ${o} ${t} ${e.value}`}function Xr(e){process.stdout.write(tp(e)+`
2908
- `)}import{existsSync as np,mkdirSync as op,writeFileSync as rp}from"fs";import{homedir as zr,platform as sp}from"os";import{join as wt}from"path";import In from"picocolors";function ip(){if(sp()==="win32"){let t=process.env.LOCALAPPDATA||wt(zr(),"AppData","Local");return wt(t,"nebutra")}let e=process.env.XDG_CONFIG_HOME;return e?wt(e,"nebutra"):wt(zr(),".config","nebutra")}function ap(){let e=process.env.NEBUTRA_TELEMETRY;return e==="0"||e==="false"||e==="no"}function Jr(e,t){try{op(e,{recursive:!0}),rp(t,"")}catch{}}function Qr(){if(!process.stderr.isTTY||!process.stdin.isTTY||process.env.CI)return;let e=ip(),t=wt(e,"first-run-acked");try{if(np(t))return}catch{return}if(ap()){Jr(e,t);return}let o=[`${In.cyan("\u2139")} Nebutra collects anonymous usage analytics to improve the scaffolder.`,` Opt out at any time: ${In.dim("export NEBUTRA_TELEMETRY=0")}`,` Privacy policy: ${In.dim("https://nebutra.com/legal/cli-analytics")}`,""];try{process.stderr.write(o.join(`
2909
- `))}catch{}Jr(e,t)}import dt from"fs";import ye from"path";import*as D from"@clack/prompts";var Se="my-app",cp=new Set([".DS_Store",".Spotlight-V100",".Trashes","Thumbs.db","desktop.ini"]),Zr=new Set(["package.json","node_modules","pnpm-workspace.yaml","pnpm-lock.yaml","yarn.lock","package-lock.json","bun.lockb","turbo.json"]);function Tn(e){let t=e.trim();return t==="."||t==="./"||t===".\\"}function xn(e){if(!dt.existsSync(e))return!0;let t;try{t=dt.readdirSync(e)}catch{return!1}return t.every(n=>cp.has(n)||n===".git")}function Rn(e){if(!dt.existsSync(e))return!1;let t;try{t=dt.readdirSync(e)}catch{return!0}return t.some(n=>Zr.has(n))}function pp(e=process.cwd()){return xn(e)&&!Rn(e)}function es(e){let t=e.trim();if(!t)return"Please enter a project name.";if(t.length>128)return"Name is too long (max 128 characters).";if(!Tn(t)&&!(/[\\/]/.test(t)||ye.isAbsolute(t))&&!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(t))return"Use letters, numbers, dots, underscores, or hyphens (start with a letter or number)."}function lt(e,t=process.cwd()){let n=e.trim()||Se;if(Tn(n)){let a=ye.resolve(t);return{targetDir:".",projectName:ye.basename(a)||Se,absoluteDir:a}}if(ye.isAbsolute(n)||n.startsWith("./")||n.startsWith(".\\")||n.startsWith("../")||n.startsWith("..\\")||n.includes("/")||n.includes("\\")){let a=ye.resolve(t,n);return{targetDir:n,projectName:ye.basename(a)||Se,absoluteDir:a}}let r=es(n);if(r)throw new Error(r);let s=`./${n}`,i=ye.resolve(t,n);return{targetDir:s,projectName:n,absoluteDir:i}}async function ts(e={}){let t=e.cwd??process.cwd(),n=e.onCancel??(()=>{process.stdout.write(`Cancelled
2910
- `),process.exit(130)}),o=pp(t),r=ye.basename(t)||t,s=await D.select({message:"Create the project\u2026",options:[{value:"new",label:"In a new folder",hint:o?void 0:"recommended from home or a parent directory"},{value:"current",label:"In the current directory",hint:o?`${r} looks empty \u2014 good to go`:t}],initialValue:o?"current":"new"});if(D.isCancel(s)&&n(),s==="current"){if(Rn(t)){let c=dt.readdirSync(t).filter(p=>Zr.has(p)).slice(0,4).join(", ");D.log.error(`Current directory already looks like a project (${c}). Choose a new folder, or pass a different path: create-sailor my-app`),n()}if(!xn(t)){let c=await D.confirm({message:"Current directory is not empty. Scaffold files will be mixed in \u2014 continue?",initialValue:!1});(D.isCancel(c)||!c)&&n()}return lt(".",t)}let i=await D.text({message:"What should we call your project?",placeholder:Se,defaultValue:Se,validate:c=>{let p=(c??"").trim()||Se;if(Tn(p)||/[\\/]/.test(p)||ye.isAbsolute(p))try{lt(p,t);return}catch(d){return d instanceof Error?d.message:"Invalid path."}return es(p)}});D.isCancel(i)&&n();let a=lt(String(i).trim()||Se,t);if(dt.existsSync(a.absoluteDir)&&!xn(a.absoluteDir)){Rn(a.absoluteDir)&&(D.log.error(`Folder "${a.projectName}" already exists and looks like a project. Pick another name.`),n());let c=await D.confirm({message:`Folder "${a.projectName}" is not empty. Continue?`,initialValue:!1});(D.isCancel(c)||!c)&&n()}return a}import*as j from"@clack/prompts";function lp(e){return{...e.config,region:e.region,orm:e.orm,database:e.database,databaseHost:e.databaseHost,payment:e.payment,aiMode:e.aiMode,aiRouting:e.aiRouting,aiProviders:e.aiProviders,customAiEndpoint:e.customAiEndpoint,deployTarget:e.deployTarget,deployTargets:e.deployTargets,docs:e.docs,i18n:e.i18n,email:e.email,storage:e.storage,monitoring:e.monitoring,analytics:e.analytics,sms:e.sms,queue:e.queue,search:e.search,cache:e.cache,notifications:e.notifications,webhooks:e.webhooks,cms:e.cms,featureFlags:e.featureFlags,captcha:e.captcha,mcp:e.mcp,metering:e.metering,billingMode:e.billingMode,idp:e.idp,accessGate:e.accessGate}}function dp(e){e.previewSelections=It([{flag:"queue",provider:e.queue},{flag:"search",provider:e.search},{flag:"notifications",provider:e.notifications},{flag:"webhooks",provider:e.webhooks},{flag:"feature-flags",provider:e.featureFlags},{flag:"captcha",provider:e.captcha},{flag:"access-gate",provider:e.accessGate}]),e.config=lp(e)}async function up(e,t){let n=await j.select({message:"Payment provider",options:[{value:"stripe",label:"Stripe",hint:"global default"},{value:"lemon",label:"Lemon Squeezy"},{value:"wechat",label:"WeChat Pay",hint:"CN"},{value:"alipay",label:"Alipay",hint:"CN"},{value:"none",label:"None"}],initialValue:e.paymentChoice});j.isCancel(n)&&t();let o=String(n);e.payment=gt(o),e.paymentChoice=ft(o);let r=await j.select({message:"Email provider",options:rt.map(a=>({value:a.id,label:a.name,hint:a.region==="cn"?"CN":a.id==="none"?void 0:"global"})),initialValue:e.email});j.isCancel(r)&&t(),e.email=String(r);let s=await j.select({message:"Object storage",options:Re.map(a=>({value:a.id,label:a.name,hint:a.region==="cn"?"CN":a.id==="none"?void 0:"global"})),initialValue:e.storage});j.isCancel(s)&&t(),e.storage=String(s);let i=await j.select({message:"Deploy target",options:[{value:"vercel",label:"Vercel",hint:"recommended for Next.js"},{value:"railway",label:"Railway"},{value:"cloudflare",label:"Cloudflare"},{value:"selfhost",label:"Self-host / Docker"}],initialValue:e.deployTarget});j.isCancel(i)&&t(),e.deployTarget=yt(String(i)),e.deployTargets=Ct(e.deployTarget),dp(e)}async function ns(e,t){let n={...e,config:{...e.config},aiProviders:[...e.aiProviders],socialLoginIds:[...e.socialLoginIds],previewSelections:[...e.previewSelections],deployTargets:{...e.deployTargets},waveToggles:{...e.waveToggles}},o=await j.select({message:"Create project with these settings?",options:[{value:"proceed",label:"Yes, create project",hint:"use region defaults above"},{value:"customize",label:"Customize key providers",hint:"payment \xB7 email \xB7 storage \xB7 deploy"},{value:"cancel",label:"Cancel"}],initialValue:"proceed"});return(j.isCancel(o)||o==="cancel")&&t(),o==="customize"&&(await up(n,t),j.log.success("Defaults updated \u2014 scaffolding with your choices.")),n}function xe(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2911
- `)}function gp(e,t,n,o,r){let{region:s,orm:i,database:a,paymentChoice:c,docs:p,socialLoginIds:d,aiMode:u,aiProviders:A,customAiEndpoint:h,deployTarget:g,metering:E,payment:S,billingMode:m,idp:_,mcp:H,waveToggles:M,previewSelections:he}=t,{email:le,storage:ee,monitoring:$,analytics:K,sms:C,queue:W,search:de,cache:P,notifications:Ee,webhooks:ze,cms:Je,featureFlags:ve,captcha:v}=t,R=A.length,w=[`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}`}`,...d.length>0?[`social-login \u2192 generate ${d.length} callback route${d.length===1?"":"s"} + SocialLoginButtons.tsx (${d.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`})`]:[],...R>0||h?[`ai-providers \u2192 generate ${u} registry seed + env (${R}${h?" + custom":""} provider${R===1&&!h?"":"s"})`]:[],...le!=="none"?[`email \u2192 configure ${le}`]:[],...ee!=="none"?[`storage \u2192 configure ${ee}`]:[],...$!=="none"?[`monitoring \u2192 configure ${$}`]:[],...K!=="none"?[`analytics \u2192 configure ${K}`]:[],...C!=="none"?[`sms \u2192 configure ${C}`]:[],...W!=="none"?[`queue \u2192 configure ${W}`]:[],...de!=="none"?[`search \u2192 configure ${de}`]:[],...P!=="none"?[`cache \u2192 configure ${P}`]:[],...Ee!=="none"?[`notifications \u2192 configure ${Ee}`]:[],...ze!=="none"?[`webhooks \u2192 configure ${ze}`]:[],...Je!=="none"?[`cms \u2192 configure ${Je}`]:[],...ve!=="none"?[`feature-flags \u2192 configure ${ve}`]:[],...v!=="none"?[`captcha \u2192 configure ${v}`]:[],`mcp \u2192 ${H==="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}`]:[],..._!=="clerk"?[`idp \u2192 ${_}`]:[],`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)",...g!=="none"?[`deploy \u2192 inject ${g} 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 I of w)xe(!0,{event:"plan",action:I});for(let I of he)xe(!0,{event:"warn",step:I.flag,provider:I.provider,packageStatus:I.status});xe(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2906
+ `;function Hr(){process.stdout.write(tp)}import qt from"picocolors";function Wr(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function np(e){let t=Wr()?"\u25B8":"->",n=`[${e.index}/${e.total}]`,o=e.label.padEnd(18," ");return Wr()?`${qt.dim(n)} ${qt.bold(o)} ${qt.dim(t)} ${qt.cyan(e.value)}`:`${n} ${o} ${t} ${e.value}`}function Xr(e){process.stdout.write(np(e)+`
2907
+ `)}import{existsSync as op,mkdirSync as rp,writeFileSync as sp}from"fs";import{homedir as zr,platform as ip}from"os";import{join as Pt}from"path";import In from"picocolors";function ap(){if(ip()==="win32"){let t=process.env.LOCALAPPDATA||Pt(zr(),"AppData","Local");return Pt(t,"nebutra")}let e=process.env.XDG_CONFIG_HOME;return e?Pt(e,"nebutra"):Pt(zr(),".config","nebutra")}function cp(){let e=process.env.NEBUTRA_TELEMETRY;return e==="0"||e==="false"||e==="no"}function Jr(e,t){try{rp(e,{recursive:!0}),sp(t,"")}catch{}}function Qr(){if(!process.stderr.isTTY||!process.stdin.isTTY||process.env.CI)return;let e=ap(),t=Pt(e,"first-run-acked");try{if(op(t))return}catch{return}if(cp()){Jr(e,t);return}let o=[`${In.cyan("\u2139")} Nebutra collects anonymous usage analytics to improve the scaffolder.`,` Opt out at any time: ${In.dim("export NEBUTRA_TELEMETRY=0")}`,` Privacy policy: ${In.dim("https://nebutra.com/legal/cli-analytics")}`,""];try{process.stderr.write(o.join(`
2908
+ `))}catch{}Jr(e,t)}import dt from"fs";import ye from"path";import*as D from"@clack/prompts";var Se="my-app",pp=new Set([".DS_Store",".Spotlight-V100",".Trashes","Thumbs.db","desktop.ini"]),Zr=new Set(["package.json","node_modules","pnpm-workspace.yaml","pnpm-lock.yaml","yarn.lock","package-lock.json","bun.lockb","turbo.json"]);function Tn(e){let t=e.trim();return t==="."||t==="./"||t===".\\"}function xn(e){if(!dt.existsSync(e))return!0;let t;try{t=dt.readdirSync(e)}catch{return!1}return t.every(n=>pp.has(n)||n===".git")}function Rn(e){if(!dt.existsSync(e))return!1;let t;try{t=dt.readdirSync(e)}catch{return!0}return t.some(n=>Zr.has(n))}function lp(e=process.cwd()){return xn(e)&&!Rn(e)}function es(e){let t=e.trim();if(!t)return"Please enter a project name.";if(t.length>128)return"Name is too long (max 128 characters).";if(!Tn(t)&&!(/[\\/]/.test(t)||ye.isAbsolute(t))&&!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(t))return"Use letters, numbers, dots, underscores, or hyphens (start with a letter or number)."}function lt(e,t=process.cwd()){let n=e.trim()||Se;if(Tn(n)){let a=ye.resolve(t);return{targetDir:".",projectName:ye.basename(a)||Se,absoluteDir:a}}if(ye.isAbsolute(n)||n.startsWith("./")||n.startsWith(".\\")||n.startsWith("../")||n.startsWith("..\\")||n.includes("/")||n.includes("\\")){let a=ye.resolve(t,n);return{targetDir:n,projectName:ye.basename(a)||Se,absoluteDir:a}}let r=es(n);if(r)throw new Error(r);let s=`./${n}`,i=ye.resolve(t,n);return{targetDir:s,projectName:n,absoluteDir:i}}async function ts(e={}){let t=e.cwd??process.cwd(),n=e.onCancel??(()=>{process.stdout.write(`Cancelled
2909
+ `),process.exit(130)}),o=lp(t),r=ye.basename(t)||t,s=await D.select({message:"Create the project\u2026",options:[{value:"new",label:"In a new folder",hint:o?void 0:"recommended from home or a parent directory"},{value:"current",label:"In the current directory",hint:o?`${r} looks empty \u2014 good to go`:t}],initialValue:o?"current":"new"});if(D.isCancel(s)&&n(),s==="current"){if(Rn(t)){let c=dt.readdirSync(t).filter(p=>Zr.has(p)).slice(0,4).join(", ");D.log.error(`Current directory already looks like a project (${c}). Choose a new folder, or pass a different path: create-sailor my-app`),n()}if(!xn(t)){let c=await D.confirm({message:"Current directory is not empty. Scaffold files will be mixed in \u2014 continue?",initialValue:!1});(D.isCancel(c)||!c)&&n()}return lt(".",t)}let i=await D.text({message:"What should we call your project?",placeholder:Se,defaultValue:Se,validate:c=>{let p=(c??"").trim()||Se;if(Tn(p)||/[\\/]/.test(p)||ye.isAbsolute(p))try{lt(p,t);return}catch(d){return d instanceof Error?d.message:"Invalid path."}return es(p)}});D.isCancel(i)&&n();let a=lt(String(i).trim()||Se,t);if(dt.existsSync(a.absoluteDir)&&!xn(a.absoluteDir)){Rn(a.absoluteDir)&&(D.log.error(`Folder "${a.projectName}" already exists and looks like a project. Pick another name.`),n());let c=await D.confirm({message:`Folder "${a.projectName}" is not empty. Continue?`,initialValue:!1});(D.isCancel(c)||!c)&&n()}return a}import*as j from"@clack/prompts";function dp(e){return{...e.config,region:e.region,orm:e.orm,database:e.database,databaseHost:e.databaseHost,payment:e.payment,aiMode:e.aiMode,aiRouting:e.aiRouting,aiProviders:e.aiProviders,customAiEndpoint:e.customAiEndpoint,deployTarget:e.deployTarget,deployTargets:e.deployTargets,docs:e.docs,i18n:e.i18n,email:e.email,storage:e.storage,monitoring:e.monitoring,analytics:e.analytics,sms:e.sms,queue:e.queue,search:e.search,cache:e.cache,notifications:e.notifications,webhooks:e.webhooks,cms:e.cms,featureFlags:e.featureFlags,captcha:e.captcha,mcp:e.mcp,metering:e.metering,billingMode:e.billingMode,idp:e.idp,accessGate:e.accessGate}}function up(e){e.previewSelections=It([{flag:"queue",provider:e.queue},{flag:"search",provider:e.search},{flag:"notifications",provider:e.notifications},{flag:"webhooks",provider:e.webhooks},{flag:"feature-flags",provider:e.featureFlags},{flag:"captcha",provider:e.captcha},{flag:"access-gate",provider:e.accessGate}]),e.config=dp(e)}async function mp(e,t){let n=await j.select({message:"Payment provider",options:[{value:"stripe",label:"Stripe",hint:"global default"},{value:"lemon",label:"Lemon Squeezy"},{value:"wechat",label:"WeChat Pay",hint:"CN"},{value:"alipay",label:"Alipay",hint:"CN"},{value:"none",label:"None"}],initialValue:e.paymentChoice});j.isCancel(n)&&t();let o=String(n);e.payment=gt(o),e.paymentChoice=ft(o);let r=await j.select({message:"Email provider",options:rt.map(a=>({value:a.id,label:a.name,hint:a.region==="cn"?"CN":a.id==="none"?void 0:"global"})),initialValue:e.email});j.isCancel(r)&&t(),e.email=String(r);let s=await j.select({message:"Object storage",options:Re.map(a=>({value:a.id,label:a.name,hint:a.region==="cn"?"CN":a.id==="none"?void 0:"global"})),initialValue:e.storage});j.isCancel(s)&&t(),e.storage=String(s);let i=await j.select({message:"Deploy target",options:[{value:"vercel",label:"Vercel",hint:"recommended for Next.js"},{value:"railway",label:"Railway"},{value:"cloudflare",label:"Cloudflare"},{value:"selfhost",label:"Self-host / Docker"}],initialValue:e.deployTarget});j.isCancel(i)&&t(),e.deployTarget=yt(String(i)),e.deployTargets=Ct(e.deployTarget),up(e)}async function ns(e,t){let n={...e,config:{...e.config},aiProviders:[...e.aiProviders],socialLoginIds:[...e.socialLoginIds],previewSelections:[...e.previewSelections],deployTargets:{...e.deployTargets},waveToggles:{...e.waveToggles}},o=await j.select({message:"Create project with these settings?",options:[{value:"proceed",label:"Yes, create project",hint:"use region defaults above"},{value:"customize",label:"Customize key providers",hint:"payment \xB7 email \xB7 storage \xB7 deploy"},{value:"cancel",label:"Cancel"}],initialValue:"proceed"});return(j.isCancel(o)||o==="cancel")&&t(),o==="customize"&&(await mp(n,t),j.log.success("Defaults updated \u2014 scaffolding with your choices.")),n}function xe(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2910
+ `)}function fp(e,t,n,o,r){let{region:s,orm:i,database:a,paymentChoice:c,docs:p,socialLoginIds:d,aiMode:u,aiProviders:A,customAiEndpoint:h,deployTarget:g,metering:E,payment:S,billingMode:m,idp:_,mcp:H,waveToggles:M,previewSelections:he}=t,{email:le,storage:ee,monitoring:V,analytics:K,sms:C,queue:W,search:de,cache:w,notifications:Ee,webhooks:ze,cms:Je,featureFlags:ve,captcha:v}=t,R=A.length,P=[`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}`}`,...d.length>0?[`social-login \u2192 generate ${d.length} callback route${d.length===1?"":"s"} + SocialLoginButtons.tsx (${d.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`})`]:[],...R>0||h?[`ai-providers \u2192 generate ${u} registry seed + env (${R}${h?" + custom":""} provider${R===1&&!h?"":"s"})`]:[],...le!=="none"?[`email \u2192 configure ${le}`]:[],...ee!=="none"?[`storage \u2192 configure ${ee}`]:[],...V!=="none"?[`monitoring \u2192 configure ${V}`]:[],...K!=="none"?[`analytics \u2192 configure ${K}`]:[],...C!=="none"?[`sms \u2192 configure ${C}`]:[],...W!=="none"?[`queue \u2192 configure ${W}`]:[],...de!=="none"?[`search \u2192 configure ${de}`]:[],...w!=="none"?[`cache \u2192 configure ${w}`]:[],...Ee!=="none"?[`notifications \u2192 configure ${Ee}`]:[],...ze!=="none"?[`webhooks \u2192 configure ${ze}`]:[],...Je!=="none"?[`cms \u2192 configure ${Je}`]:[],...ve!=="none"?[`feature-flags \u2192 configure ${ve}`]:[],...v!=="none"?[`captcha \u2192 configure ${v}`]:[],`mcp \u2192 ${H==="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}`]:[],..._!=="clerk"?[`idp \u2192 ${_}`]:[],`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)",...g!=="none"?[`deploy \u2192 inject ${g} 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 I of P)xe(!0,{event:"plan",action:I});for(let I of he)xe(!0,{event:"warn",step:I.flag,provider:I.provider,packageStatus:I.status});xe(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2912
2911
  `+L.bold(`Dry run \u2014 planned actions:
2913
- `));for(let I of w)process.stdout.write(` \u2022 ${I}
2912
+ `));for(let I of P)process.stdout.write(` \u2022 ${I}
2914
2913
  `);if(he.length>0){process.stdout.write(`
2915
2914
  `+L.bold(L.yellow(`Preview-status providers selected:
2916
2915
  `)));for(let I of he)process.stdout.write(L.yellow(`\u26A0 ${I.flag}=${I.provider}
2917
2916
  `))}process.stdout.write(L.dim(`
2918
2917
  No files were written.
2919
- `))}}async function fp(){let e=Bn();e.parse(process.argv);let t=e.opts(),[n]=e.args;t.help&&(Hr(),process.exit(0));let o=!!t.json,r=!!t.dryRun,i=!!t.yes||!process.stdin.isTTY;if(o||(Qr(),Gr()),xe(o,{event:"start",version:z}),!t.pm)try{mp("pnpm --version",{stdio:"ignore"})}catch{o||process.stderr.write(`
2918
+ `))}}async function yp(){let e=jn();e.parse(process.argv);let t=e.opts(),[n]=e.args;t.help&&(Hr(),process.exit(0));let o=!!t.json,r=!!t.dryRun,i=!!t.yes||!process.stdin.isTTY;if(o||(Qr(),Gr()),xe(o,{event:"start",version:z}),!t.pm)try{gp("pnpm --version",{stdio:"ignore"})}catch{o||process.stderr.write(`
2920
2919
  ${L.red("\u2718")} ${L.bold("pnpm is required")} but was not found on PATH.
2921
2920
 
2922
2921
  The scaffold uses pnpm workspaces + Turborepo. Install pnpm first:
@@ -2930,13 +2929,13 @@ Then retry: ${L.cyan("pnpm dlx create-sailor@latest")}
2930
2929
  ${L.red("\u2718")} ${E}
2931
2930
 
2932
2931
  `),xe(o,{event:"error",code:"INVALID_PROJECT_NAME",message:E}),process.exit(1)}else if(i){let g=lt(Se);c=g.targetDir,p=g.projectName}else{let g=await ts({onCancel:a});c=g.targetDir,p=g.projectName,o||process.stdout.write(L.dim(` \u2192 ${g.absoluteDir}
2933
- `))}let d=t.pm??qn(),u=await oo(t,o),A=[["Project",p],["Region",u.region],["Auth",u.auth],["Payment",u.paymentChoice],["AI",`${u.aiMode}${u.aiProviders.length>0?` (${u.aiProviders.join(", ")})`:""}`],["Database",`${u.database} \xB7 ${u.databaseHost}`],["Email",u.email],["Storage",u.storage],["Deploy",u.deployTarget]];u.socialLoginIds.length>0&&A.push(["Social login",u.socialLoginIds.map(g=>Ze.find(E=>E.id===g)?.name??g).join(", ")]),o?A.forEach(([g,E],S)=>{xe(!0,{event:"step",step:g,value:E,index:S+1,total:A.length})}):(process.stdout.write(L.dim(`
2932
+ `))}let d=t.pm??Yn(),u=await no(t,o),A=[["Project",p],["Region",u.region],["Auth",u.auth],["Payment",u.paymentChoice],["AI",`${u.aiMode}${u.aiProviders.length>0?` (${u.aiProviders.join(", ")})`:""}`],["Database",`${u.database} \xB7 ${u.databaseHost}`],["Email",u.email],["Storage",u.storage],["Deploy",u.deployTarget]];u.socialLoginIds.length>0&&A.push(["Social login",u.socialLoginIds.map(g=>Ze.find(E=>E.id===g)?.name??g).join(", ")]),o?A.forEach(([g,E],S)=>{xe(!0,{event:"step",step:g,value:E,index:S+1,total:A.length})}):(process.stdout.write(L.dim(`
2934
2933
  Plan
2935
2934
  `)),A.forEach(([g,E],S)=>{Xr({index:S+1,total:A.length,label:g,value:E})}),process.stdout.write(`
2936
- `)),!i&&!o&&(u=await ns(u,a)),r&&(gp(o,u,c,d,t),process.exit(0));let h=async()=>{process.stdout.write(`
2935
+ `)),!i&&!o&&(u=await ns(u,a)),r&&(fp(o,u,c,d,t),process.exit(0));let h=async()=>{process.stdout.write(`
2937
2936
  `+L.red(`\u2718 Cancelled
2938
2937
  `)),os.existsSync(c)&&await rs.confirm({message:`Cleanup partial install at ${c}?`,initialValue:!0})===!0&&(os.rmSync(c,{recursive:!0,force:!0}),process.stdout.write(L.dim(` \u2713 Removed ${c}
2939
2938
  `))),process.exit(130)};process.on("SIGINT",h);try{await qr({resolvedTarget:c,projectName:p,resolvedPm:d,opts:t,useJson:o,resolved:u,startedAt:Date.now()}),process.exit(0)}catch(g){let E=g instanceof Error?g.message:String(g);o?xe(!0,{event:"error",message:E}):process.stdout.write(L.red(`
2940
2939
  \u2718 Failed: ${E}
2941
- `)),process.exit(1)}}fp().catch(e=>{process.stderr.write(String(e)+`
2940
+ `)),process.exit(1)}}yp().catch(e=>{process.stderr.write(String(e)+`
2942
2941
  `),process.exit(1)});