create-sailor 1.9.2 → 1.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +6 -1
  2. package/dist/index.js +200 -195
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import{a as Cn}from"./chunk-PA4CKDRJ.js";import"./chunk-IYWUY3VA.js";import{execSync as Wc}from"child_process";import qr from"fs";import Gr from"path";import*as ot from"@clack/prompts";import F from"picocolors";import{Command as Jr}from"commander";import xn from"fs";import Vt from"path";import{fileURLToPath as Xr}from"url";function zr(){try{let t=Vt.dirname(Xr(import.meta.url));for(let n=0;n<4;n++){let o=Vt.join(t,"package.json");if(xn.existsSync(o)){let r=xn.readFileSync(o,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=Vt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var X=zr();var Qr="create-sailor";function Rn(){let e=new Jr;return e.name(Qr).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(X,"-v, --version").helpOption(!1).argument("[name]","project directory",void 0).option("-p, --pm <id>","npm | pnpm | yarn | bun").option("--region <id>","global | cn | hybrid").option("--orm <id>","prisma (default, primary) | drizzle (dual-ORM: adds db-drizzle alongside Prisma \u2014 Postgres only)").option("--db <id>","postgres | mysql | sqlite | none \u2014 engine (Prisma provider)").option("--db-host <id>","local | supabase | neon | vercel-postgres | planetscale | railway | aliyun-rds | tencent-cdb | none \u2014 managed-provider (region default: supabase global, local cn)").option("--auth <id>","clerk | betterauth | nextauth | supabase | none").option("--social-login <ids>","CN social login providers \u2014 wechat | qq | dingtalk | workweixin | feishu | weibo (comma-separated)").option("--payment <id>","stripe | lemon | wechat | alipay | none").option("--ai <mode-or-ids>","topology shorthand (gateway | direct | custom | none) OR comma-separated provider ids (e.g. openai,anthropic)").option("--deploy <target>","vercel | railway | cloudflare | selfhost").option("--docs <id>","fumadocs | mintlify | docusaurus | nextra | vitepress | none").option("--email <id>","resend | postmark | ses | aliyun-dm | tencent-ses | netease | none").option("--storage <id>","r2 | s3 | supabase-storage | aliyun-oss | tencent-cos | qiniu | none").option("--monitoring <id>","sentry | datadog | aliyun-arms | tingyun | none").option("--analytics <id>","posthog | plausible | umami | baidu | sensors | none").option("--sms <id>","twilio | aliyun-sms | tencent-sms | yunpian | none").option("--queue <id>","qstash | bullmq | sqs | none").option("--search <id>","meilisearch | typesense | algolia | pgvector | none").option("--cache <id>","upstash-redis | vercel-kv | redis | dragonfly | none").option("--notifications <id>","novu | knock | custom | none").option("--webhooks <id>","svix | custom | none").option("--cms <id>","sanity | contentful | strapi | none").option("--feature-flags <id>","vercel-flags | growthbook | configcat | none").option("--captcha <id>","turnstile | hcaptcha | aliyun-slide | none").option("--mcp <mode>","on | off (default: on)").option("--metering <mode>","auto | on | off (default: auto \u2014 auto-on when payment is set)").option("--billing-mode <mode>","usage | seat | credits (default: usage)").option("--idp <id>","clerk | oauth-server (default: clerk)").option("--access-gate <mode>","none | invite (default: none)").option("--cron-jobs <bool>","true | false \u2014 scaffold scheduled cron handlers (default: true)").option("--audit-log <bool>","true | false \u2014 enable /settings/audit-log + arch test (default: false \u2014 @nebutra/audit is WIP)").option("--api-keys <bool>","true | false \u2014 enable /settings/api-keys page (default: true)").option("--command-palette <bool>","true | false \u2014 enable \u2318K command palette (default: true)").option("--cookie-consent <bool>","true | false \u2014 enable GDPR/CCPA cookie banner (default: true)").option("--legal-pages <bool>","true | false \u2014 enable dynamic /legal/[slug] route (default: true)").option("--china-compliance <bool>","true | false \u2014 enable @nebutra/china-compliance + ICP footer (default: true when --region=cn, otherwise false)").option("--i18n","enable i18n").option("--no-i18n","disable i18n").option("--with-workflows","scaffold workflows/ (inngest + n8n + pusher stubs)").option("--with-python-backend","scaffold backends/python/ (FastAPI stub \u2014 only when TS-by-Default ADR exception applies)").option("--no-install","skip package install").option("--no-git","skip git init").option("-y, --yes","accept all defaults (non-interactive)").option("--dry-run","preview actions without writing files").option("--json","machine-readable output").option("--no-color","disable color output").option("-h, --help","show help"),e}import Nn from"picocolors";var $t=[{id:"local",name:"Local / Self-hosted Docker",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres:postgres@localhost:5432/$PROJECT",comment:"Local Postgres via docker-compose (pnpm infra:up)"}],docs:"https://www.postgresql.org/docs/",description:"Docker on localhost. You operate it.",tier:"self-hosted"},{id:"supabase",name:"Supabase",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:5432/postgres?sslmode=require",comment:"Supabase session pooler \u2014 use for runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://postgres:<password>@db.<project-ref>.supabase.co:5432/postgres?sslmode=require",comment:"Supabase direct \u2014 use for Prisma migrations"},{name:"NEXT_PUBLIC_SUPABASE_URL",placeholder:"https://<project>.supabase.co"},{name:"NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY",placeholder:""},{name:"NEXT_PUBLIC_SUPABASE_ANON_KEY",placeholder:""},{name:"SUPABASE_PUBLISHABLE_KEY",placeholder:""},{name:"SUPABASE_SERVICE_ROLE_KEY",placeholder:""}],docs:"https://supabase.com/docs",description:"Managed Postgres + auth/storage/realtime/edge-functions.",tier:"managed"},{id:"neon",name:"Neon",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>-pooler.<region>.neon.tech/<db>?sslmode=require",comment:"Neon pooled \u2014 runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>.<region>.neon.tech/<db>?sslmode=require",comment:"Neon direct (no -pooler) \u2014 migrations"}],docs:"https://neon.tech/docs",description:"Serverless Postgres with branching and scale-to-zero.",tier:"managed"},{id:"vercel-postgres",name:"Vercel Postgres",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"$POSTGRES_PRISMA_URL",comment:"Vercel Marketplace injects POSTGRES_PRISMA_URL automatically"},{name:"DIRECT_URL",placeholder:"$POSTGRES_URL_NON_POOLING",comment:"Vercel Marketplace injects POSTGRES_URL_NON_POOLING automatically"}],docs:"https://vercel.com/docs/storage/vercel-postgres",description:"Neon-backed, auto-provisioned via Vercel Marketplace.",tier:"managed"},{id:"planetscale",name:"PlanetScale Postgres",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres.<branch-id>:<password>@<host>.horizon.psdb.cloud:6432/postgres?sslmode=require",comment:"PlanetScale Postgres pooled/PgBouncer URL \u2014 runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://postgres.<branch-id>:<password>@<host>.horizon.psdb.cloud:5432/postgres?sslmode=require",comment:"PlanetScale Postgres direct URL \u2014 Prisma migrations"}],docs:"https://planetscale.com/docs/postgres",description:"Managed Postgres with branching; compatible with Sailor migrations.",tier:"managed"},{id:"railway",name:"Railway",region:"global",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"$DATABASE_URL",comment:"Railway service env var; injected when you link a Postgres service"}],docs:"https://docs.railway.app/databases/postgresql",description:"Generalist managed infra; standard TCP Postgres/MySQL.",tier:"managed"},{id:"aliyun-rds",name:"Aliyun RDS",region:"cn",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@<rds-instance>.rds.aliyuncs.com:5432/<db>",comment:"Aliyun RDS Postgres \u2014 internal VPC endpoint recommended"}],docs:"https://www.alibabacloud.com/help/en/rds",description:"Aliyun RDS \u2014 China compliance + intranet routing.",tier:"managed"},{id:"tencent-cdb",name:"Tencent CloudDB (CDB)",region:"cn",supportedEngines:["mysql","postgresql"],envVars:[{name:"DATABASE_URL",placeholder:"mysql://<user>:<pwd>@<cdb-instance>.tencentcdb.com:3306/<db>",comment:"Tencent CloudDB \u2014 VPC endpoint recommended"}],docs:"https://intl.cloud.tencent.com/document/product/236",description:"Tencent CloudDB \u2014 China compliance.",tier:"managed"},{id:"none",name:"None",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[],docs:"",description:"Skip database scaffolding.",tier:"self-hosted"}];function st(e){return $t.find(t=>t.id===e)}function Tn(e){return e==="cn"||e==="hybrid"?"local":"supabase"}var it=[{id:"r2",name:"Cloudflare R2",region:"global",envVars:["R2_ACCOUNT_ID","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY","R2_BUCKET"],docs:"https://developers.cloudflare.com/r2/api/s3/api/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"s3",name:"AWS S3",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_S3_REGION","S3_BUCKET"],docs:"https://docs.aws.amazon.com/s3/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"supabase-storage",name:"Supabase Storage",region:"global",envVars:["SUPABASE_URL","SUPABASE_SERVICE_ROLE_KEY","SUPABASE_BUCKET"],docs:"https://supabase.com/docs/guides/storage",pkg:"@supabase/supabase-js",pkgVersion:"^2.45.4"},{id:"aliyun-oss",name:"\u963F\u91CC\u4E91 OSS",region:"cn",envVars:["ALIYUN_OSS_ACCESS_KEY","ALIYUN_OSS_ACCESS_SECRET","ALIYUN_OSS_REGION","ALIYUN_OSS_BUCKET"],docs:"https://help.aliyun.com/product/31815.html",pkg:"ali-oss",pkgVersion:"^6.21.0"},{id:"tencent-cos",name:"\u817E\u8BAF\u4E91 COS",region:"cn",envVars:["TENCENT_COS_SECRET_ID","TENCENT_COS_SECRET_KEY","TENCENT_COS_BUCKET","TENCENT_COS_REGION"],docs:"https://cloud.tencent.com/document/product/436",pkg:"cos-nodejs-sdk-v5",pkgVersion:"^2.13.7"},{id:"qiniu",name:"\u4E03\u725B\u4E91 Kodo",region:"cn",envVars:["QINIU_ACCESS_KEY","QINIU_SECRET_KEY","QINIU_BUCKET","QINIU_DOMAIN"],docs:"https://developer.qiniu.com/kodo",pkg:"qiniu",pkgVersion:"^7.14.0"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function Kt(e){let t=e==="supabase"?"supabase-storage":e;return it.some(n=>n.id===t)?t:void 0}function kn(e){let t=Kt(e);return t?it.find(n=>n.id===t):void 0}var sp=it.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ln(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function Yt(e){switch(e){case"postgres":case"postgresql":return"postgresql";case"mysql":return"mysql";case"sqlite":return"sqlite";case"none":return"none";default:return"postgresql"}}function qt(e,t,n){let o=e?.trim().toLowerCase()??Tn(t),r=st(o);if(!r){let i=$t.map(a=>a.id).join(", ");throw new Error(`Unknown --db-host="${o}". Valid: ${i}`)}let s=n;return r.forcedEngine&&s!=="none"&&s!==r.forcedEngine&&(s=r.forcedEngine),{hostId:r.id,engine:s}}function Gt(e){return e==="drizzle"?"drizzle":"prisma"}function Ht(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function Wt(e){if(!e)return"stripe";let t=e.toLowerCase();return t==="lemon"||t==="lemonsqueezy"?"lemon":t==="wechat"?"wechat":t==="alipay"?"alipay":t==="none"?"none":"stripe"}function Xt(e){if(!e)return"clerk";let t=e.toLowerCase();return t==="betterauth"||t==="better-auth"?"betterauth":t==="nextauth"||t==="next-auth"||t==="authjs"||t==="auth.js"?"nextauth":t==="supabase"||t==="supabase-auth"?"supabase":t==="none"?"none":"clerk"}var Zr=new Set(["gateway","direct","custom","none"]);function zt(e){if(!e)return!1;let t=e.trim().toLowerCase();return Zr.has(t)}function Jt(e){if(!e)return["openai"];if(zt(e))return[];let t=e.split(",").map(n=>n.trim().toLowerCase());return t.includes("none")?[]:t}function Un(e,t){let n=e??t;return Kt(n)??n}var On={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function Qt(e,t){if(!e)return"fumadocs";let n=e.toLowerCase();if(n==="fumadocs"||n==="none")return n;if(n in On){let o=On[n];return t?process.stdout.write(JSON.stringify({event:"notice",kind:"docs-fallback",requested:n,effective:"fumadocs"})+`
3
- `):process.stdout.write(Nn.yellow(`\u26A0 ${o} support is coming in v1.2. Falling back to fumadocs.
4
- `)+Nn.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
5
- `)),"fumadocs"}return"fumadocs"}function Zt(e){switch(e){case"vercel":return"vercel";case"railway":return"railway";case"cloudflare":return"cloudflare";case"selfhost":return"selfhost";case"none":return"none";default:return"vercel"}}function en(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function Dn(e){return{...e==="cn"?{email:"aliyun-dm",storage:"aliyun-oss",monitoring:"sentry",analytics:"baidu",sms:"aliyun-sms"}:e==="hybrid"?{email:"resend",storage:"aliyun-oss",monitoring:"sentry",analytics:"posthog",sms:"aliyun-sms"}:{email:"resend",storage:"r2",monitoring:"sentry",analytics:"posthog",sms:"twilio"},queue:"none",search:"none",cache:e==="global"?"upstash-redis":e==="cn"?"redis":"upstash-redis",notifications:"none",webhooks:"none",cms:"none",featureFlags:"none",captcha:"none",mcp:"on",metering:"auto",billingMode:"usage",idp:"clerk",accessGate:"none"}}function tn(e){return e==="cn"?"wechat":"stripe"}import*as Y from"@clack/prompts";import hs from"picocolors";var nn=[{id:"anthropic",name:"Anthropic",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://docs.anthropic.com",envVarPrefix:"ANTHROPIC",requiredEnvVars:["ANTHROPIC_API_KEY"]},{id:"openai",name:"OpenAI",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.openai.com/docs",envVarPrefix:"OPENAI",requiredEnvVars:["OPENAI_API_KEY"]},{id:"deepseek",name:"DeepSeek",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.deepseek.com/api-docs",envVarPrefix:"DEEPSEEK",requiredEnvVars:["DEEPSEEK_API_KEY"]},{id:"xai",name:"xAI (Grok)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://docs.x.ai/api",envVarPrefix:"XAI",requiredEnvVars:["XAI_API_KEY"]},{id:"moonshot",name:"Moonshot (Kimi)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.moonshot.cn/docs",envVarPrefix:"MOONSHOT",requiredEnvVars:["MOONSHOT_API_KEY","MOONSHOT_BASE_URL"]},{id:"google",name:"Google Gemini",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://ai.google.dev/gemini-api/docs",envVarPrefix:"GOOGLE_GENERATIVE_AI",requiredEnvVars:["GOOGLE_GENERATIVE_AI_API_KEY"]},{id:"mistral",name:"Mistral AI",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://docs.mistral.ai",envVarPrefix:"MISTRAL",requiredEnvVars:["MISTRAL_API_KEY"]},{id:"cohere",name:"Cohere",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://docs.cohere.com",envVarPrefix:"COHERE",requiredEnvVars:["COHERE_API_KEY"]},{id:"perplexity",name:"Perplexity",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://docs.perplexity.ai",baseURL:"https://api.perplexity.ai",envVarPrefix:"PERPLEXITY",requiredEnvVars:["PERPLEXITY_API_KEY"]},{id:"ai21",name:"AI21 Labs",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://docs.ai21.com",baseURL:"https://api.ai21.com/studio/v1",envVarPrefix:"AI21",requiredEnvVars:["AI21_API_KEY"]},{id:"upstage",name:"Upstage (Solar)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://developers.upstage.ai/docs",baseURL:"https://api.upstage.ai/v1/solar",envVarPrefix:"UPSTAGE",requiredEnvVars:["UPSTAGE_API_KEY"]},{id:"siliconflow",name:"\u7845\u57FA\u6D41\u52A8 SiliconFlow",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://docs.siliconflow.cn",baseURL:"https://api.siliconflow.cn/v1",envVarPrefix:"SILICONFLOW",requiredEnvVars:["SILICONFLOW_API_KEY"]},{id:"volcengine-ark",name:"\u706B\u5C71\u5F15\u64CE ARK (\u8C46\u5305)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://www.volcengine.com/docs/82379",baseURL:"https://ark.cn-beijing.volces.com/api/v3",envVarPrefix:"ARK",requiredEnvVars:["ARK_API_KEY"]},{id:"bailian",name:"\u767E\u70BC Bailian (\u901A\u4E49)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://help.aliyun.com/zh/model-studio",baseURL:"https://dashscope.aliyuncs.com/compatible-mode/v1",envVarPrefix:"DASHSCOPE",requiredEnvVars:["DASHSCOPE_API_KEY"]},{id:"zhipu",name:"\u667A\u8C31 AI Zhipu",category:"\u56FD\u5185\u5E73\u53F0",status:"ai-sdk",docs:"https://docs.bigmodel.cn",baseURL:"https://open.bigmodel.cn/api/paas/v4",envVarPrefix:"ZHIPU",requiredEnvVars:["ZHIPU_API_KEY"]},{id:"baichuan",name:"\u767E\u5DDD\u667A\u80FD Baichuan",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.baichuan-ai.com/docs",baseURL:"https://api.baichuan-ai.com/v1",envVarPrefix:"BAICHUAN",requiredEnvVars:["BAICHUAN_API_KEY"]},{id:"minimax",name:"MiniMax (ABAB)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.minimaxi.com/document/guides",baseURL:"https://api.minimax.chat/v1",envVarPrefix:"MINIMAX",requiredEnvVars:["MINIMAX_API_KEY","MINIMAX_GROUP_ID"]},{id:"stepfun",name:"\u9636\u8DC3\u661F\u8FB0 StepFun",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.stepfun.com/docs",baseURL:"https://api.stepfun.com/v1",envVarPrefix:"STEPFUN",requiredEnvVars:["STEPFUN_API_KEY"]},{id:"sensetime",name:"\u5546\u6C64 SenseNova",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.sensenova.cn/docs",baseURL:"https://token.sensenova.cn/v1",envVarPrefix:"SENSENOVA",requiredEnvVars:["SENSENOVA_API_KEY"]},{id:"tencent",name:"\u817E\u8BAF\u6DF7\u5143 Hunyuan",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://cloud.tencent.com/document/product/1729",baseURL:"https://api.hunyuan.cloud.tencent.com/v1",envVarPrefix:"HUNYUAN",requiredEnvVars:["HUNYUAN_API_KEY"]},{id:"lingyi",name:"\u96F6\u4E00\u4E07\u7269 Yi",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.lingyiwanwu.com/docs",baseURL:"https://api.lingyiwanwu.com/v1",envVarPrefix:"YI",requiredEnvVars:["YI_API_KEY"]},{id:"openrouter",name:"OpenRouter",category:"\u7EDF\u4E00\u7F51\u5173",status:"opencode",docs:"https://openrouter.ai/docs",envVarPrefix:"OPENROUTER",requiredEnvVars:["OPENROUTER_API_KEY"]},{id:"vercel-gateway",name:"Vercel AI Gateway",category:"\u7EDF\u4E00\u7F51\u5173",status:"opencode",docs:"https://vercel.com/docs/ai-gateway",envVarPrefix:"AI_GATEWAY",requiredEnvVars:["AI_GATEWAY_API_KEY"]},{id:"litellm",name:"LiteLLM Proxy",category:"\u7EDF\u4E00\u7F51\u5173",status:"cn-compatible",docs:"https://docs.litellm.ai",baseURL:"http://localhost:4000/v1",envVarPrefix:"LITELLM",requiredEnvVars:["LITELLM_API_KEY"]},{id:"portkey",name:"Portkey",category:"\u7EDF\u4E00\u7F51\u5173",status:"cn-compatible",docs:"https://portkey.ai/docs",baseURL:"https://api.portkey.ai/v1",envVarPrefix:"PORTKEY",requiredEnvVars:["PORTKEY_API_KEY"]},{id:"aws-bedrock",name:"AWS Bedrock",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://aws.amazon.com/bedrock/",envVarPrefix:"AWS_BEDROCK",requiredEnvVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_REGION"]},{id:"azure-openai",name:"Azure OpenAI",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://azure.microsoft.com/en-us/products/cognitive-services/openai-service/",envVarPrefix:"AZURE_OPENAI",requiredEnvVars:["AZURE_OPENAI_API_KEY","AZURE_OPENAI_ENDPOINT"]},{id:"gcp-vertex",name:"GCP Vertex AI",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://cloud.google.com/vertex-ai",envVarPrefix:"GOOGLE_VERTEX",requiredEnvVars:["GOOGLE_APPLICATION_CREDENTIALS"]},{id:"groq",name:"Groq",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://console.groq.com/docs",envVarPrefix:"GROQ",requiredEnvVars:["GROQ_API_KEY"]},{id:"fireworks",name:"Fireworks AI",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://docs.fireworks.ai",envVarPrefix:"FIREWORKS",requiredEnvVars:["FIREWORKS_API_KEY"]},{id:"together",name:"Together AI",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://docs.together.ai",envVarPrefix:"TOGETHER",requiredEnvVars:["TOGETHER_API_KEY"]},{id:"huggingface",name:"Hugging Face",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://huggingface.co/docs/inference-providers",envVarPrefix:"HF",requiredEnvVars:["HF_API_KEY"]},{id:"replicate",name:"Replicate",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://replicate.com/docs",envVarPrefix:"REPLICATE",requiredEnvVars:["REPLICATE_API_TOKEN"]},{id:"lepton",name:"Lepton AI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://www.lepton.ai/docs",baseURL:"https://api.lepton.ai/v1",envVarPrefix:"LEPTON",requiredEnvVars:["LEPTON_API_KEY"]},{id:"anyscale",name:"Anyscale Endpoints",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://docs.endpoints.anyscale.com/",baseURL:"https://api.endpoints.anyscale.com/v1",envVarPrefix:"ANYSCALE",requiredEnvVars:["ANYSCALE_API_KEY"]},{id:"octoai",name:"OctoAI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://octoai.cloud/docs",baseURL:"https://text.octoai.run/v1",envVarPrefix:"OCTOAI",requiredEnvVars:["OCTOAI_TOKEN"]},{id:"deepinfra",name:"DeepInfra",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://deepinfra.com/docs",baseURL:"https://api.deepinfra.com/v1/openai",envVarPrefix:"DEEPINFRA",requiredEnvVars:["DEEPINFRA_API_KEY"]},{id:"novita",name:"Novita AI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://novita.ai/docs",baseURL:"https://api.novita.ai/v3/openai",envVarPrefix:"NOVITA",requiredEnvVars:["NOVITA_API_KEY"]},{id:"black-forest-labs",name:"Black Forest Labs (FLUX)",category:"\u591A\u6A21\u6001",status:"ai-sdk",docs:"https://docs.bfl.ml",envVarPrefix:"BFL",requiredEnvVars:["BFL_API_KEY"]},{id:"elevenlabs",name:"ElevenLabs (TTS)",category:"\u591A\u6A21\u6001",status:"ai-sdk",docs:"https://elevenlabs.io/docs",envVarPrefix:"ELEVENLABS",requiredEnvVars:["ELEVENLABS_API_KEY"]},{id:"runway",name:"Runway (Video)",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://runwayml.com",envVarPrefix:"RUNWAY",requiredEnvVars:["RUNWAY_API_KEY"]},{id:"luma",name:"Luma (Video)",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://lumalabs.ai",envVarPrefix:"LUMA",requiredEnvVars:["LUMA_API_KEY"]},{id:"midjourney",name:"Midjourney",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://docs.midjourney.com",envVarPrefix:"MIDJOURNEY",requiredEnvVars:[]},{id:"ollama",name:"Ollama (\u672C\u5730)",category:"\u672C\u5730\u90E8\u7F72",status:"opencode",docs:"https://github.com/ollama/ollama",baseURL:"http://localhost:11434/v1",envVarPrefix:"OLLAMA",requiredEnvVars:["OLLAMA_BASE_URL"]},{id:"lmstudio",name:"LM Studio",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://lmstudio.ai/docs",baseURL:"http://localhost:1234/v1",envVarPrefix:"LMSTUDIO",requiredEnvVars:[]},{id:"vllm",name:"vLLM",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://docs.vllm.ai",baseURL:"http://localhost:8000/v1",envVarPrefix:"VLLM",requiredEnvVars:[]},{id:"tgi",name:"HF TGI",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://huggingface.co/docs/text-generation-inference",baseURL:"http://localhost:8080/v1",envVarPrefix:"TGI",requiredEnvVars:[]}],dp=nn.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var es=["openai","anthropic","google"],ts=["openai"];function on(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let n=t.length>0?t:[...es];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:[...ts];return{mode:"direct",providerIds:n,customEndpoint:e.customEndpoint,routing:{profile:"direct-adapters",providerSeed:n,runtimeGovernance:!1}}}case"custom":return{mode:"custom",providerIds:t,customEndpoint:e.customEndpoint,routing:{profile:"openai-compatible",providerSeed:t,runtimeGovernance:!0}};case"none":return{mode:"none",providerIds:[],routing:{profile:"disabled",providerSeed:[],runtimeGovernance:!1}}}}var We=[{id:"wechat",name:"\u5FAE\u4FE1\u5F00\u653E\u5E73\u53F0",region:"cn",envVars:["WECHAT_APP_ID","WECHAT_APP_SECRET"],docs:"https://open.weixin.qq.com/cgi-bin/showdocument",callbackUrl:"/api/auth/callback/wechat",tokenEndpoint:"https://api.weixin.qq.com/sns/oauth2/access_token"},{id:"qq",name:"QQ \u767B\u5F55",region:"cn",envVars:["QQ_APP_ID","QQ_APP_KEY"],docs:"https://wiki.connect.qq.com",callbackUrl:"/api/auth/callback/qq",tokenEndpoint:"https://graph.qq.com/oauth2.0/token"},{id:"dingtalk",name:"\u9489\u9489",region:"cn",envVars:["DINGTALK_APP_ID","DINGTALK_APP_SECRET"],docs:"https://open.dingtalk.com/document/",callbackUrl:"/api/auth/callback/dingtalk",tokenEndpoint:"https://api.dingtalk.com/v1.0/oauth2/userAccessToken"},{id:"workweixin",name:"\u4F01\u4E1A\u5FAE\u4FE1",region:"cn",envVars:["WORKWEIXIN_CORP_ID","WORKWEIXIN_AGENT_ID","WORKWEIXIN_SECRET"],docs:"https://developer.work.weixin.qq.com",callbackUrl:"/api/auth/callback/workweixin",tokenEndpoint:"https://qyapi.weixin.qq.com/cgi-bin/gettoken"},{id:"feishu",name:"\u98DE\u4E66 / Lark",region:"cn",envVars:["FEISHU_APP_ID","FEISHU_APP_SECRET"],docs:"https://open.feishu.cn/document/",callbackUrl:"/api/auth/callback/feishu",tokenEndpoint:"https://open.feishu.cn/open-apis/authen/v1/access_token"},{id:"weibo",name:"\u5FAE\u535A",region:"cn",envVars:["WEIBO_APP_KEY","WEIBO_APP_SECRET"],docs:"https://open.weibo.com/wiki/",callbackUrl:"/api/auth/callback/weibo",tokenEndpoint:"https://api.weibo.com/oauth2/access_token"}],ns=new Set(We.map(e=>e.id));function Mn(e){return We.find(t=>t.id===e)}function Fn(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)ns.has(r)&&!o.has(r)&&(n.push(r),o.add(r));return n}import ee from"fs";import k from"path";import{fileURLToPath as ps}from"url";var jn=["web","landing","auth","admin","design-docs","sailor-docs","router","forge","typelens","gateway","python-ai"],os={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"},rs={frontend:"vercel",edgeGateway:"cloudflare-workers",originBackend:"ecs-docker"};function ss(e){return jn.includes(e)}function is(e){if(!ss(e))throw new Error(`Unknown deploy service '${e}'. Deploy targets apply only to apps/backends, not packages.`)}function as(e){return is(e),os[e]}function cs(e){let t=as(e);return rs[t]}function Bn(){return Object.fromEntries(jn.map(e=>[e,cs(e)]))}var ls=ps(import.meta.url),Vn=k.dirname(ls),ds="cloudflare-pages",us="standalone",ms="railway";function rn(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 gs(){let e=[k.join(Vn,"..","templates","deploy"),k.join(Vn,"..","..","templates","deploy")];for(let t of e)if(ee.existsSync(t))return t;return e[0]}function Kn(e){let t=Bn();switch(e){case"cloudflare":return rn(t,ds,"cloudflare-workers","ecs-docker");case"selfhost":return rn(t,us,"ecs-docker","ecs-docker");case"railway":return rn(t,ms,"railway","railway");case"none":case"vercel":return t}}function fs(e){return`DEPLOY_TARGET_${e.toUpperCase().replace(/-/g,"_")}`}async function $n(e,t){let n=k.join(e,"backends","gateway");ee.existsSync(n)&&await ee.promises.copyFile(k.join(t,"wrangler.gateway.toml"),k.join(n,"wrangler.toml"))}async function Yn(e,t){let n=k.join(e,".env.example"),o;try{o=await ee.promises.readFile(n,"utf8")}catch(i){if(i.code==="ENOENT")return;throw i}if(o.includes("# Deployment Targets"))return;let s=["","# Deployment Targets",...Object.entries(t).map(([i,a])=>`${fs(i)}="${a}"`)].join(`
6
- `);await ee.promises.appendFile(n,`${s}
7
- `)}async function qn(e,t){if(t==="none")return;let n=gs();t==="vercel"?(await ee.promises.copyFile(k.join(n,"vercel.json"),k.join(e,"vercel.json")),await $n(e,n)):t==="railway"?await ee.promises.copyFile(k.join(n,"railway.toml"),k.join(e,"railway.toml")):t==="cloudflare"?(await ee.promises.copyFile(k.join(n,"wrangler.toml"),k.join(e,"wrangler.toml")),await $n(e,n)):t==="selfhost"&&(await ee.promises.copyFile(k.join(n,"docker-compose.yml"),k.join(e,"docker-compose.yml")),await ee.promises.copyFile(k.join(n,"Dockerfile.web"),k.join(e,"Dockerfile.web")))}var ys={qstash:"foundation",bullmq:"foundation",upstash:"foundation",sqs:"foundation",meilisearch:"foundation",typesense:"foundation",algolia:"foundation",pgvector:"foundation","vercel-flags":"foundation",growthbook:"foundation",configcat:"foundation",turnstile:"wip",hcaptcha:"wip","aliyun-slide":"wip",invite:"foundation"};function Ss(e){return e?ys[e]??"stable":"stable"}function Xe(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function Ee(e){switch(e){case"stable":return"Production-ready.";case"foundation":return"Foundation status \u2014 core contracts work, but production use still requires provider credentials, adapter wiring, or a verified integration contract.";case"wip":return"WIP \u2014 actively being built, should not be used in production.";case"deprecated":return"Deprecated \u2014 scheduled for removal, do not use."}}function Gn(e){let t=[];for(let{flag:n,provider:o}of e){if(!o||o==="none")continue;let r=Ss(o);r!=="stable"&&t.push({flag:n,provider:o,status:r})}return t}function ve(e,t){if(e===void 0)return t;let n=String(e).trim().toLowerCase();return n==="true"||n==="1"||n==="yes"||n==="on"?!0:n==="false"||n==="0"||n==="no"||n==="off"?!1:t}function Hn(e,t){let n=t==="cn";return{cronJobs:ve(e.cronJobs,!0),auditLog:ve(e.auditLog,!1),apiKeys:ve(e.apiKeys,!0),webhooks:ve(e.webhooks,!0),commandPalette:ve(e.commandPalette,!0),cookieConsent:ve(e.cookieConsent,!0),legalPages:ve(e.legalPages,!0),chinaCompliance:ve(e.chinaCompliance,n)}}async function Es(e,t,n,o){let r={};return t||(r.region=()=>Y.select({message:"Target region?",options:[{value:"global",label:"global \u2014 \u6D77\u5916\u4F18\u5148"},{value:"cn",label:"cn \u2014 \u56FD\u5185\u4F18\u5148"},{value:"hybrid",label:"hybrid \u2014 \u53CC\u8F68\uFF08\u56FD\u5185+\u51FA\u6D77\uFF09"}],initialValue:"global"})),n||(r.auth=()=>Y.select({message:"Auth provider?",options:[{value:"clerk",label:"Clerk",hint:"managed, fastest setup"},{value:"betterauth",label:"Better Auth",hint:"self-hosted, modern (2FA / passkeys / RBAC)"},{value:"nextauth",label:"NextAuth (Auth.js v5)",hint:"self-hosted, mature, large ecosystem"},{value:"supabase",label:"Supabase Auth",hint:"managed auth with Supabase storage/realtime ecosystem"},{value:"none",label:"None"}],initialValue:"clerk"})),o||(r.aiMode=()=>Y.select({message:"AI topology?",options:[{value:"gateway",label:"Multi-provider AI Gateway / router",hint:"recommended"},{value:"direct",label:"Direct SDK/provider adapters"},{value:"custom",label:"OpenAI-compatible endpoint"},{value:"none",label:"Skip AI"}],initialValue:"gateway"}),r.aiProviders=({results:s})=>{if(s.aiMode!=="direct")return Promise.resolve([]);let i=nn.map(a=>({value:a.id,label:`[${a.category}] ${a.name}`}));return Y.multiselect({message:"Select direct AI provider adapters (expert path)",options:i,initialValues:["openai"],required:!1})},r.customAiName=({results:s})=>s.aiMode==="custom"?Y.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),r.customAiBaseUrl=({results:s})=>s.aiMode==="custom"?Y.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:i=>{if(!i?.length)return"Base URL is required."}}):Promise.resolve(void 0),r.customAiApiKeyEnv=({results:s})=>s.aiMode==="custom"?Y.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0)),Object.keys(r).length===0?{}:await Y.group(r,{onCancel:()=>{process.stdout.write(hs.red(`\u2718 Cancelled
8
- `)),process.exit(130)}})}async function Wn(e,t){let n=!!e.region,o=!!e.auth,r=!!e.payment,s=!!e.ai,i=!!e.email,a=!!e.storage,c=!!e.monitoring,p=!!e.analytics,u=!!e.sms,d=e.i18n!==void 0,b=!!e.yes||!process.stdin.isTTY,f,h,S,m,_,G,D,fe=Fn(e.socialLogin),pe,Z,j,$,C,H,le;if(b){f=en(e.region),h=Gt(e.orm);{let K=Yt(e.db),yt=qt(e.dbHost,f,K);S=yt.engine,m=yt.hostId}let W=r?e.payment:tn(f);_=Ht(W),G=Wt(W),D=Xt(e.auth);let He="gateway";if(s){let K=e.ai?.trim().toLowerCase()??"";zt(K)?He=K:He="direct"}let rt=on({mode:He,providerIds:s?Jt(e.ai):void 0});pe=rt.mode,Z=rt.routing,j=rt.providerIds,C=Zt(e.deploy),H=Qt(e.docs,t),le=d?!!e.i18n:!0}else{let W=await Es(e,n,o,s);f=en(n?e.region:W.region),h=Gt(e.orm);{let yt=Yt(e.db),In=qt(e.dbHost,f,yt);S=In.engine,m=In.hostId}let He=r?e.payment:tn(f);_=Ht(He),G=Wt(He),D=Xt(o?e.auth:W.auth);let rt=W.aiMode==="custom"?{name:W.customAiName??"custom",baseURL:W.customAiBaseUrl??"",apiKeyEnvName:W.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,K=on({mode:s?e.ai?.trim().toLowerCase()==="none"?"none":"direct":W.aiMode??"gateway",providerIds:s?Jt(e.ai):W.aiProviders,customEndpoint:rt});pe=K.mode,Z=K.routing,j=K.providerIds,K.customEndpoint&&($={name:K.customEndpoint.name,baseURL:K.customEndpoint.baseURL,apiKeyEnvName:K.customEndpoint.apiKeyEnvName}),C=Zt(e.deploy),H=Qt(e.docs,t),le=d?!!e.i18n:!0}let P=Dn(f),ye=i?e.email:P.email,qe=Un(a?e.storage:void 0,P.storage),Ge=c?e.monitoring:P.monitoring,Se=p?e.analytics:P.analytics,E=u?e.sms:P.sms,T=e.queue??P.queue,I=e.search??P.search,x=e.cache??P.cache,Dt=e.notifications??P.notifications,Mt=e.webhooks??P.webhooks,vn=e.cms??P.cms,Ft=e.featureFlags??P.featureFlags,jt=e.captcha??P.captcha,bn=e.mcp??P.mcp,_n=e.metering??P.metering,Pn=e.billingMode??P.billingMode,wn=e.idp??P.idp,Bt=e.accessGate==="invite"?"invite":P.accessGate,An=Kn(C),he=Hn({cronJobs:e.cronJobs,auditLog:e.auditLog,apiKeys:e.apiKeys,commandPalette:e.commandPalette,cookieConsent:e.cookieConsent,legalPages:e.legalPages,chinaCompliance:e.chinaCompliance},f),Hr=Gn([{flag:"queue",provider:T},{flag:"search",provider:I},{flag:"notifications",provider:Dt},{flag:"webhooks",provider:Mt},{flag:"feature-flags",provider:Ft},{flag:"captcha",provider:jt},{flag:"access-gate",provider:Bt}]),Wr={region:f,orm:h,database:S,databaseHost:m,payment:_,aiMode:pe,aiRouting:Z,aiProviders:j,customAiEndpoint:$,deployTarget:C,deployTargets:An,docs:H,i18n:le,email:ye,storage:qe,monitoring:Ge,analytics:Se,sms:E,queue:T,search:I,cache:x,notifications:Dt,webhooks:Mt,cms:vn,featureFlags:Ft,captcha:jt,mcp:bn,metering:_n,billingMode:Pn,idp:wn,accessGate:Bt,cronJobs:he.cronJobs,auditLog:he.auditLog,apiKeys:he.apiKeys,commandPalette:he.commandPalette,cookieConsent:he.cookieConsent,legalPages:he.legalPages,chinaCompliance:he.chinaCompliance};return{region:f,orm:h,database:S,databaseHost:m,payment:_,paymentChoice:G,auth:D,socialLoginIds:fe,aiMode:pe,aiRouting:Z,aiProviders:j,customAiEndpoint:$,deployTarget:C,deployTargets:An,docs:H,i18n:le,email:ye,storage:qe,monitoring:Ge,analytics:Se,sms:E,queue:T,search:I,cache:x,notifications:Dt,webhooks:Mt,cms:vn,featureFlags:Ft,captcha:jt,mcp:bn,metering:_n,billingMode:Pn,idp:wn,accessGate:Bt,waveToggles:he,previewSelections:Hr,config:Wr}}import{execFileSync as Ot}from"child_process";import Lt from"fs";import Ke from"path";import gt from"picocolors";import Mc from"update-notifier";import w from"picocolors";function vs(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Xn(e){let t=vs(),n=t?"\u2693":"-",o=t?"\u25B8":"->",r=t?"\u2605":"*",s=t?"\u{1F4E7}":"*",a=["",` ${t?w.bold(`${n} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`):`${n} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`}`,"",` ${t?w.bold("Next:"):"Next:"}`,` ${o} cd ${e.targetDir}`];e.skippedInstall&&a.push(` ${o} pnpm install (if --no-install was set)`),a.push(` ${o} fill in .env.local ${t?w.dim("\u2192 add provider keys before booting apps"):"-> add provider keys before booting apps"}`,` ${o} pnpm db:migrate ${t?w.dim("\u2192 sync Prisma schema"):"-> sync Prisma schema"}`,` ${o} pnpm db:seed ${t?w.dim("\u2192 load example tenants and records"):"-> load example tenants and records"}`,` ${o} pnpm dev ${t?w.dim("\u2192 http://localhost:3000"):"-> http://localhost:3000"}`,"",` ${t?w.bold("Customize:"):"Customize:"}`,` ${o} pnpm brand:init ${t?w.dim("\u2192 create brand.config.ts"):"-> create brand.config.ts"}`,` ${o} pnpm brand:apply ${t?w.dim("\u2192 propagate brand changes"):"-> propagate brand changes"}`,` ${o} pnpm preset:env ${t?w.dim("\u2192 review preset env requirements"):"-> review preset env requirements"}`,"",` ${t?w.bold("Useful scripts:"):"Useful scripts:"}`,` ${o} pnpm infra:up ${t?w.dim("\u2192 start local PostgreSQL/Redis/ClickHouse"):"-> start local PostgreSQL/Redis/ClickHouse"}`,` ${o} pnpm generate:api-types ${t?w.dim("\u2192 refresh shared API client types"):"-> refresh shared API client types"}`,` ${o} pnpm lint ${t?w.dim("\u2192 quick repo sanity check"):"-> quick repo sanity check"}`,` ${o} pnpm audit ${t?w.dim("\u2192 scan deps for known CVEs"):"-> scan deps for known CVEs"}`);let c=e.previewSelections??[];if(c.length>0){let A=t?w.bold(w.yellow("\u26A0 Preview features selected:")):"!! Preview features selected:";a.push("",` ${A}`);for(let b of c){let f=Xe(b.status),h=` ${o} ${b.flag} (${b.provider}) ${f}`;a.push(t?w.yellow(h):h)}a.push("",` ${t?w.dim(Ee("foundation")):Ee("foundation")}`,` ${t?w.dim("You may need to contribute the provider integration yourself."):"You may need to contribute the provider integration yourself."}`,` ${t?w.dim("See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"):"See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"}`)}let p=e.waveFeatures??{},u=A=>A!==!1,d=[];u(p.apiKeys)&&d.push("Manage API keys at /settings/api-keys"),u(p.auditLog)&&d.push("View audit log at /settings/audit-log"),d.push("Configure webhooks at /settings/webhooks"),u(p.commandPalette)&&d.push("Press Cmd/Ctrl+K to open the command palette"),d.push("Edit notification preferences at /settings/notifications"),d.push("Export your data at /settings/account/export"),p.chinaCompliance&&d.push("China deployments \u2014 see packages/ops/china-compliance/README.md"),a.push("",` ${t?w.bold("What you can do next:"):"What you can do next:"}`);for(let A of d)a.push(` ${o} ${A}`);a.push("",` ${t?w.bold("Ship faster:"):"Ship faster:"}`,` ${r} Star us https://github.com/nebutra/nebutra-sailor`,` ${s} Free license https://nebutra.com/get-license`,""),process.stdout.write(a.join(`
2
+ import{a as Ln}from"./chunk-PA4CKDRJ.js";import"./chunk-IYWUY3VA.js";import{execSync as ip}from"child_process";import ts from"fs";import*as ns from"@clack/prompts";import D from"picocolors";import{Command as as}from"commander";import Un from"fs";import qt from"path";import{fileURLToPath as ss}from"url";function is(){try{let t=qt.dirname(ss(import.meta.url));for(let n=0;n<4;n++){let o=qt.join(t,"package.json");if(Un.existsSync(o)){let r=Un.readFileSync(o,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=qt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var z=is();var cs="create-sailor";function Dn(){let e=new as;return e.name(cs).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 jn from"picocolors";var Gt=[{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 pt(e){return Gt.find(t=>t.id===e)}function Mn(e){return e==="cn"||e==="hybrid"?"local":"supabase"}var lt=[{id:"r2",name:"Cloudflare R2",region:"global",envVars:["R2_ACCOUNT_ID","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY","R2_BUCKET"],docs:"https://developers.cloudflare.com/r2/api/s3/api/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"s3",name:"AWS S3",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_S3_REGION","S3_BUCKET"],docs:"https://docs.aws.amazon.com/s3/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"supabase-storage",name:"Supabase Storage",region:"global",envVars:["SUPABASE_URL","SUPABASE_SERVICE_ROLE_KEY","SUPABASE_BUCKET"],docs:"https://supabase.com/docs/guides/storage",pkg:"@supabase/supabase-js",pkgVersion:"^2.45.4"},{id:"aliyun-oss",name:"\u963F\u91CC\u4E91 OSS",region:"cn",envVars:["ALIYUN_OSS_ACCESS_KEY","ALIYUN_OSS_ACCESS_SECRET","ALIYUN_OSS_REGION","ALIYUN_OSS_BUCKET"],docs:"https://help.aliyun.com/product/31815.html",pkg:"ali-oss",pkgVersion:"^6.21.0"},{id:"tencent-cos",name:"\u817E\u8BAF\u4E91 COS",region:"cn",envVars:["TENCENT_COS_SECRET_ID","TENCENT_COS_SECRET_KEY","TENCENT_COS_BUCKET","TENCENT_COS_REGION"],docs:"https://cloud.tencent.com/document/product/436",pkg:"cos-nodejs-sdk-v5",pkgVersion:"^2.13.7"},{id:"qiniu",name:"\u4E03\u725B\u4E91 Kodo",region:"cn",envVars:["QINIU_ACCESS_KEY","QINIU_SECRET_KEY","QINIU_BUCKET","QINIU_DOMAIN"],docs:"https://developer.qiniu.com/kodo",pkg:"qiniu",pkgVersion:"^7.14.0"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function Ht(e){let t=e==="supabase"?"supabase-storage":e;return lt.some(n=>n.id===t)?t:void 0}function Fn(e){let t=Ht(e);return t?lt.find(n=>n.id===t):void 0}var Sp=lt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function $n(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function Wt(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 Xt(e,t,n){let o=e?.trim().toLowerCase()??Mn(t),r=pt(o);if(!r){let i=Gt.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 zt(e){return e==="drizzle"?"drizzle":"prisma"}function Jt(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function Qt(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 Zt(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 ps=new Set(["gateway","direct","custom","none"]);function en(e){if(!e)return!1;let t=e.trim().toLowerCase();return ps.has(t)}function tn(e){if(!e)return["openai"];if(en(e))return[];let t=e.split(",").map(n=>n.trim().toLowerCase());return t.includes("none")?[]:t}function Vn(e,t){let n=e??t;return Ht(n)??n}var Bn={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function nn(e,t){if(!e)return"fumadocs";let n=e.toLowerCase();if(n==="fumadocs"||n==="none")return n;if(n in Bn){let o=Bn[n];return t?process.stdout.write(JSON.stringify({event:"notice",kind:"docs-fallback",requested:n,effective:"fumadocs"})+`
3
+ `):process.stdout.write(jn.yellow(`\u26A0 ${o} support is coming in v1.2. Falling back to fumadocs.
4
+ `)+jn.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
5
+ `)),"fumadocs"}return"fumadocs"}function on(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 rn(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function Kn(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 sn(e){return e==="cn"?"wechat":"stripe"}import*as q from"@clack/prompts";import xs from"picocolors";var an=[{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:[]}],Pp=an.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var ls=["openai","anthropic","google"],ds=["openai"];function cn(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let n=t.length>0?t:[...ls];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:[...ds];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 Je=[{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"}],us=new Set(Je.map(e=>e.id));function Yn(e){return Je.find(t=>t.id===e)}function qn(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)us.has(r)&&!o.has(r)&&(n.push(r),o.add(r));return n}import te from"fs";import k from"path";import{fileURLToPath as Es}from"url";var Gn=["web","landing","auth","admin","design-docs","sailor-docs","router","forge","typelens","gateway","python-ai"],ms={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"},gs={frontend:"vercel",edgeGateway:"cloudflare-workers",originBackend:"ecs-docker"};function fs(e){return Gn.includes(e)}function ys(e){if(!fs(e))throw new Error(`Unknown deploy service '${e}'. Deploy targets apply only to apps/backends, not packages.`)}function Ss(e){return ys(e),ms[e]}function hs(e){let t=Ss(e);return gs[t]}function Hn(){return Object.fromEntries(Gn.map(e=>[e,hs(e)]))}var vs=Es(import.meta.url),Wn=k.dirname(vs),bs="cloudflare-pages",_s="standalone",Ps="railway";function pn(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 ws(){let e=[k.join(Wn,"..","templates","deploy"),k.join(Wn,"..","..","templates","deploy")];for(let t of e)if(te.existsSync(t))return t;return e[0]}function zn(e){let t=Hn();switch(e){case"cloudflare":return pn(t,bs,"cloudflare-workers","ecs-docker");case"selfhost":return pn(t,_s,"ecs-docker","ecs-docker");case"railway":return pn(t,Ps,"railway","railway");case"none":case"vercel":return t}}function As(e){return`DEPLOY_TARGET_${e.toUpperCase().replace(/-/g,"_")}`}async function Xn(e,t){let n=k.join(e,"backends","gateway");te.existsSync(n)&&await te.promises.copyFile(k.join(t,"wrangler.gateway.toml"),k.join(n,"wrangler.toml"))}async function Jn(e,t){let n=k.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])=>`${As(i)}="${a}"`)].join(`
6
+ `);await te.promises.appendFile(n,`${s}
7
+ `)}async function Qn(e,t){if(t==="none")return;let n=ws();t==="vercel"?(await te.promises.copyFile(k.join(n,"vercel.json"),k.join(e,"vercel.json")),await Xn(e,n)):t==="railway"?await te.promises.copyFile(k.join(n,"railway.toml"),k.join(e,"railway.toml")):t==="cloudflare"?(await te.promises.copyFile(k.join(n,"wrangler.toml"),k.join(e,"wrangler.toml")),await Xn(e,n)):t==="selfhost"&&(await te.promises.copyFile(k.join(n,"docker-compose.yml"),k.join(e,"docker-compose.yml")),await te.promises.copyFile(k.join(n,"Dockerfile.web"),k.join(e,"Dockerfile.web")))}var Cs={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 Is(e){return e?Cs[e]??"stable":"stable"}function Qe(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function _e(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 Zn(e){let t=[];for(let{flag:n,provider:o}of e){if(!o||o==="none")continue;let r=Is(o);r!=="stable"&&t.push({flag:n,provider:o,status:r})}return t}function Pe(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 eo(e,t){let n=t==="cn";return{cronJobs:Pe(e.cronJobs,!0),auditLog:Pe(e.auditLog,!1),apiKeys:Pe(e.apiKeys,!0),webhooks:Pe(e.webhooks,!0),commandPalette:Pe(e.commandPalette,!0),cookieConsent:Pe(e.cookieConsent,!0),legalPages:Pe(e.legalPages,!0),chinaCompliance:Pe(e.chinaCompliance,n)}}async function Rs(e,t,n,o){let r={};return t||(r.region=()=>q.select({message:"Target region?",options:[{value:"global",label:"global \u2014 \u6D77\u5916\u4F18\u5148"},{value:"cn",label:"cn \u2014 \u56FD\u5185\u4F18\u5148"},{value:"hybrid",label:"hybrid \u2014 \u53CC\u8F68\uFF08\u56FD\u5185+\u51FA\u6D77\uFF09"}],initialValue:"global"})),n||(r.auth=()=>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=an.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(xs.red(`\u2718 Cancelled
8
+ `)),process.exit(130)}})}async function to(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,m=e.i18n!==void 0,E=!!e.yes||!process.stdin.isTTY,g,h,S,u,_,H,F,he=qn(e.socialLogin),le,ee,B,K,I,W,de;if(E){g=rn(e.region),h=zt(e.orm);{let Y=Wt(e.db),vt=Xt(e.dbHost,g,Y);S=vt.engine,u=vt.hostId}let X=r?e.payment:sn(g);_=Jt(X),H=Qt(X),F=Zt(e.auth);let ze="gateway";if(s){let Y=e.ai?.trim().toLowerCase()??"";en(Y)?ze=Y:ze="direct"}let ct=cn({mode:ze,providerIds:s?tn(e.ai):void 0});le=ct.mode,ee=ct.routing,B=ct.providerIds,I=on(e.deploy),W=nn(e.docs,t),de=m?!!e.i18n:!0}else{let X=await Rs(e,n,o,s);g=rn(n?e.region:X.region),h=zt(e.orm);{let vt=Wt(e.db),On=Xt(e.dbHost,g,vt);S=On.engine,u=On.hostId}let ze=r?e.payment:sn(g);_=Jt(ze),H=Qt(ze),F=Zt(o?e.auth:X.auth);let ct=X.aiMode==="custom"?{name:X.customAiName??"custom",baseURL:X.customAiBaseUrl??"",apiKeyEnvName:X.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,Y=cn({mode:s?e.ai?.trim().toLowerCase()==="none"?"none":"direct":X.aiMode??"gateway",providerIds:s?tn(e.ai):X.aiProviders,customEndpoint:ct});le=Y.mode,ee=Y.routing,B=Y.providerIds,Y.customEndpoint&&(K={name:Y.customEndpoint.name,baseURL:Y.customEndpoint.baseURL,apiKeyEnvName:Y.customEndpoint.apiKeyEnvName}),I=on(e.deploy),W=nn(e.docs,t),de=m?!!e.i18n:!0}let P=Kn(g),Ee=i?e.email:P.email,We=Vn(a?e.storage:void 0,P.storage),Xe=c?e.monitoring:P.monitoring,ve=p?e.analytics:P.analytics,v=d?e.sms:P.sms,T=e.queue??P.queue,A=e.search??P.search,x=e.cache??P.cache,Bt=e.notifications??P.notifications,$t=e.webhooks??P.webhooks,In=e.cms??P.cms,Vt=e.featureFlags??P.featureFlags,Kt=e.captcha??P.captcha,xn=e.mcp??P.mcp,Rn=e.metering??P.metering,Tn=e.billingMode??P.billingMode,kn=e.idp??P.idp,Yt=e.accessGate==="invite"?"invite":P.accessGate,Nn=zn(I),be=eo({cronJobs:e.cronJobs,auditLog:e.auditLog,apiKeys:e.apiKeys,commandPalette:e.commandPalette,cookieConsent:e.cookieConsent,legalPages:e.legalPages,chinaCompliance:e.chinaCompliance},g),os=Zn([{flag:"queue",provider:T},{flag:"search",provider:A},{flag:"notifications",provider:Bt},{flag:"webhooks",provider:$t},{flag:"feature-flags",provider:Vt},{flag:"captcha",provider:Kt},{flag:"access-gate",provider:Yt}]),rs={region:g,orm:h,database:S,databaseHost:u,payment:_,aiMode:le,aiRouting:ee,aiProviders:B,customAiEndpoint:K,deployTarget:I,deployTargets:Nn,docs:W,i18n:de,email:Ee,storage:We,monitoring:Xe,analytics:ve,sms:v,queue:T,search:A,cache:x,notifications:Bt,webhooks:$t,cms:In,featureFlags:Vt,captcha:Kt,mcp:xn,metering:Rn,billingMode:Tn,idp:kn,accessGate:Yt,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:h,database:S,databaseHost:u,payment:_,paymentChoice:H,auth:F,socialLoginIds:he,aiMode:le,aiRouting:ee,aiProviders:B,customAiEndpoint:K,deployTarget:I,deployTargets:Nn,docs:W,i18n:de,email:Ee,storage:We,monitoring:Xe,analytics:ve,sms:v,queue:T,search:A,cache:x,notifications:Bt,webhooks:$t,cms:In,featureFlags:Vt,captcha:Kt,mcp:xn,metering:Rn,billingMode:Tn,idp:kn,accessGate:Yt,waveToggles:be,previewSelections:os,config:rs}}import{execFileSync as Mt}from"child_process";import Ft from"fs";import He from"path";import ht from"picocolors";import Hc from"update-notifier";import w from"picocolors";function Ts(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function no(e){let t=Ts(),n=t?"\u2693":"-",o=t?"\u25B8":"->",r=t?"\u2605":"*",s=t?"\u{1F4E7}":"*",i=e.targetDir==="."||e.targetDir==="./"||e.targetDir===".\\",a=i?".":e.targetDir.endsWith("/")?e.targetDir:`${e.targetDir}/`,p=["",` ${t?w.bold(`${n} Done in ${e.elapsedSec}s \xB7 ${a}`):`${n} Done in ${e.elapsedSec}s \xB7 ${a}`}`,"",` ${t?w.bold("Next:"):"Next:"}`];i||p.push(` ${o} cd ${e.targetDir}`),e.skippedInstall&&p.push(` ${o} pnpm install (if --no-install was set)`),p.push(` ${o} fill in .env.local ${t?w.dim("\u2192 add provider keys before booting apps"):"-> add provider keys before booting apps"}`,` ${o} pnpm db:migrate ${t?w.dim("\u2192 sync Prisma schema"):"-> sync Prisma schema"}`,` ${o} pnpm db:seed ${t?w.dim("\u2192 load example tenants and records"):"-> load example tenants and records"}`,` ${o} pnpm dev ${t?w.dim("\u2192 http://localhost:3000"):"-> http://localhost:3000"}`,"",` ${t?w.bold("Customize:"):"Customize:"}`,` ${o} pnpm brand:init ${t?w.dim("\u2192 create brand.config.ts"):"-> create brand.config.ts"}`,` ${o} pnpm brand:apply ${t?w.dim("\u2192 propagate brand changes"):"-> propagate brand changes"}`,` ${o} pnpm preset:env ${t?w.dim("\u2192 review preset env requirements"):"-> review preset env requirements"}`,"",` ${t?w.bold("Useful scripts:"):"Useful scripts:"}`,` ${o} pnpm infra:up ${t?w.dim("\u2192 start local PostgreSQL/Redis/ClickHouse"):"-> start local PostgreSQL/Redis/ClickHouse"}`,` ${o} pnpm generate:api-types ${t?w.dim("\u2192 refresh shared API client types"):"-> refresh shared API client types"}`,` ${o} pnpm lint ${t?w.dim("\u2192 quick repo sanity check"):"-> quick repo sanity check"}`,` ${o} pnpm audit ${t?w.dim("\u2192 scan deps for known CVEs"):"-> scan deps for known CVEs"}`);let d=e.previewSelections??[];if(d.length>0){let g=t?w.bold(w.yellow("\u26A0 Preview features selected:")):"!! Preview features selected:";p.push("",` ${g}`);for(let h of d){let S=Qe(h.status),u=` ${o} ${h.flag} (${h.provider}) ${S}`;p.push(t?w.yellow(u):u)}p.push("",` ${t?w.dim(_e("foundation")):_e("foundation")}`,` ${t?w.dim("You may need to contribute the provider integration yourself."):"You may need to contribute the provider integration yourself."}`,` ${t?w.dim("See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"):"See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"}`)}let m=e.waveFeatures??{},C=g=>g!==!1,E=[];C(m.apiKeys)&&E.push("Manage API keys at /settings/api-keys"),C(m.auditLog)&&E.push("View audit log at /settings/audit-log"),E.push("Configure webhooks at /settings/webhooks"),C(m.commandPalette)&&E.push("Press Cmd/Ctrl+K to open the command palette"),E.push("Edit notification preferences at /settings/notifications"),E.push("Export your data at /settings/account/export"),m.chinaCompliance&&E.push("China deployments \u2014 see packages/ops/china-compliance/README.md"),p.push("",` ${t?w.bold("What you can do next:"):"What you can do next:"}`);for(let g of E)p.push(` ${o} ${g}`);p.push("",` ${t?w.bold("Ship faster:"):"Ship faster:"}`,` ${r} Star us https://github.com/nebutra/nebutra-sailor`,` ${s} Free license https://nebutra.com/get-license`,""),process.stdout.write(p.join(`
9
9
  `)+`
10
- `)}import ze from"fs";import B from"path";var zn=[{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:""}],Dp=zn.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Jn(e){return zn.find(t=>t.id===e)}function bs(e){ze.mkdirSync(e,{recursive:!0})}function te(e,t){bs(B.dirname(e)),ze.writeFileSync(e,t)}function Ie(e,t){let n=B.join(e,".env.example");ze.existsSync(n)?ze.appendFileSync(n,`
11
- `+t):ze.writeFileSync(n,t)}function _s(e){let t=`"use client";
10
+ `)}import Ze from"fs";import $ from"path";var oo=[{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:""}],Wp=oo.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function ro(e){return oo.find(t=>t.id===e)}function ks(e){Ze.mkdirSync(e,{recursive:!0})}function ne(e,t){ks($.dirname(e)),Ze.writeFileSync(e,t)}function Te(e,t){let n=$.join(e,".env.example");Ze.existsSync(n)?Ze.appendFileSync(n,`
11
+ `+t):Ze.writeFileSync(n,t)}function Ns(e){let t=`"use client";
12
12
  /**
13
13
  * PostHog browser SDK \u2014 lazy-initialized on first access.
14
14
  */
@@ -91,12 +91,12 @@ export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
91
91
 
92
92
  return <>{children}</>;
93
93
  }
94
- `;te(B.join(e,"src","lib","analytics","posthog.client.ts"),t),te(B.join(e,"src","lib","analytics","posthog.server.ts"),n),te(B.join(e,"src","components","analytics","AnalyticsProvider.tsx"),o)}function Ps(){return`# PostHog \u2014 product analytics
94
+ `;ne($.join(e,"src","lib","analytics","posthog.client.ts"),t),ne($.join(e,"src","lib","analytics","posthog.server.ts"),n),ne($.join(e,"src","components","analytics","AnalyticsProvider.tsx"),o)}function Os(){return`# PostHog \u2014 product analytics
95
95
  POSTHOG_KEY=
96
96
  POSTHOG_HOST=https://us.i.posthog.com
97
97
  NEXT_PUBLIC_POSTHOG_KEY=
98
98
  NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
99
- `}function ws(e){te(B.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
99
+ `}function Ls(e){ne($.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
100
100
  /**
101
101
  * Plausible script tag \u2014 lightweight, privacy-friendly analytics.
102
102
  */
@@ -116,10 +116,10 @@ export function PlausibleScript() {
116
116
  />
117
117
  );
118
118
  }
119
- `)}function As(){return`# Plausible \u2014 privacy-friendly analytics
119
+ `)}function Us(){return`# Plausible \u2014 privacy-friendly analytics
120
120
  NEXT_PUBLIC_PLAUSIBLE_DOMAIN=
121
121
  NEXT_PUBLIC_PLAUSIBLE_SRC=https://plausible.io/js/script.js
122
- `}function Is(e){te(B.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
122
+ `}function Ds(e){ne($.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
123
123
  /**
124
124
  * Umami analytics \u2014 self-hosted OR umami.is cloud.
125
125
  */
@@ -139,10 +139,10 @@ export function UmamiScript() {
139
139
  />
140
140
  );
141
141
  }
142
- `)}function Cs(){return`# Umami \u2014 self-hostable analytics
142
+ `)}function Ms(){return`# Umami \u2014 self-hostable analytics
143
143
  NEXT_PUBLIC_UMAMI_WEBSITE_ID=
144
144
  NEXT_PUBLIC_UMAMI_SRC=https://cloud.umami.is/script.js
145
- `}function xs(e){let t=`"use client";
145
+ `}function Fs(e){let t=`"use client";
146
146
  import mixpanel from "mixpanel-browser";
147
147
 
148
148
  let initialized = false;
@@ -181,10 +181,10 @@ export function trackServer(
181
181
  if (!c) return;
182
182
  c.track(event, { distinct_id: distinctId, ...properties });
183
183
  }
184
- `;te(B.join(e,"src","lib","analytics","mixpanel.client.ts"),t),te(B.join(e,"src","lib","analytics","mixpanel.server.ts"),n)}function Rs(){return`# Mixpanel \u2014 product analytics
184
+ `;ne($.join(e,"src","lib","analytics","mixpanel.client.ts"),t),ne($.join(e,"src","lib","analytics","mixpanel.server.ts"),n)}function js(){return`# Mixpanel \u2014 product analytics
185
185
  MIXPANEL_TOKEN=
186
186
  NEXT_PUBLIC_MIXPANEL_TOKEN=
187
- `}function Ts(e){te(B.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
187
+ `}function Bs(e){ne($.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
188
188
  /**
189
189
  * \u767E\u5EA6\u7EDF\u8BA1 Baidu Tongji \u2014 hm.js \u57CB\u70B9\u811A\u672C.
190
190
  */
@@ -210,9 +210,9 @@ var _hmt = _hmt || [];
210
210
  />
211
211
  );
212
212
  }
213
- `)}function ks(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
213
+ `)}function $s(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
214
214
  NEXT_PUBLIC_BAIDU_STATS_ID=
215
- `}function Ns(e){te(B.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
215
+ `}function Vs(e){ne($.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
216
216
  /**
217
217
  * \u795E\u7B56\u5206\u6790 (Sensors Analytics) \u2014 sa-sdk-javascript \u5C01\u88C5.
218
218
  */
@@ -240,10 +240,10 @@ export function initSensors(): void {
240
240
  }
241
241
 
242
242
  export { sensors };
243
- `)}function Os(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
243
+ `)}function Ks(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
244
244
  NEXT_PUBLIC_SENSORS_SERVER_URL=
245
245
  NEXT_PUBLIC_SENSORS_APP_JS_URL=
246
- `}function Ls(e){te(B.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
246
+ `}function Ys(e){ne($.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
247
247
  /**
248
248
  * GrowingIO CDP \u2014 inline snippet installer.
249
249
  */
@@ -268,21 +268,21 @@ gdp("send");
268
268
  />
269
269
  );
270
270
  }
271
- `)}function Us(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
271
+ `)}function qs(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
272
272
  NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID=
273
- `}async function Qn(e,t,n="global"){let o=Jn(t);if(!o||o.id==="none")return;let r=B.join(e,"apps","web");if(!ze.existsSync(r))return;let s=o.id;try{switch(s){case"posthog":_s(r),Ie(e,Ps());return;case"plausible":ws(r),Ie(e,As());return;case"umami":Is(r),Ie(e,Cs());return;case"mixpanel":xs(r),Ie(e,Rs());return;case"baidu":Ts(r),Ie(e,ks());return;case"sensors":Ns(r),Ie(e,Os());return;case"growingio":Ls(r),Ie(e,Us());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 Ds=Cn("analytics");function Ms(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function Zn(e,t={}){Ms(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??Ds},onError:()=>{}});if(typeof o?.track!="function")return;let r=o.track("scaffold.completed",e);r&&typeof r.then=="function"&&await r.catch(()=>{})}catch{}})()}import q from"fs";import N from"path";function V(e){q.existsSync(e)&&q.rmSync(e,{recursive:!0,force:!0})}function St(e,t){let n=N.join(e,".env.example");q.existsSync(n)?q.appendFileSync(n,`
274
- `+t):q.writeFileSync(n,t)}function ht(e,t){if(!q.existsSync(e))return;let n=q.readFileSync(e,"utf8"),o=n.replace(/export type AuthProviderId\s*=\s*(?:"[^"]+"\s*\|\s*)+"[^"]+";/,`export type AuthProviderId = "${t}";`);o!==n&&q.writeFileSync(e,o)}function Fs(e,t){let n=N.join(e,"README.md");if(!q.existsSync(n)){q.writeFileSync(n,t);return}q.appendFileSync(n,`
275
- `+t)}async function eo(e,t){let n=N.join(e,"packages","iam","auth");if(!q.existsSync(n))return;if(t==="none"){V(n),Fs(e,`
273
+ `}async function so(e,t,n="global"){let o=ro(t);if(!o||o.id==="none")return;let r=$.join(e,"apps","web");if(!Ze.existsSync(r))return;let s=o.id;try{switch(s){case"posthog":Ns(r),Te(e,Os());return;case"plausible":Ls(r),Te(e,Us());return;case"umami":Ds(r),Te(e,Ms());return;case"mixpanel":Fs(r),Te(e,js());return;case"baidu":Bs(r),Te(e,$s());return;case"sensors":Vs(r),Te(e,Ks());return;case"growingio":Ys(r),Te(e,qs());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 Gs=Ln("analytics");function Hs(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function io(e,t={}){Hs(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??Gs},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 N from"path";function V(e){G.existsSync(e)&&G.rmSync(e,{recursive:!0,force:!0})}function bt(e,t){let n=N.join(e,".env.example");G.existsSync(n)?G.appendFileSync(n,`
274
+ `+t):G.writeFileSync(n,t)}function _t(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 Ws(e,t){let n=N.join(e,"README.md");if(!G.existsSync(n)){G.writeFileSync(n,t);return}G.appendFileSync(n,`
275
+ `+t)}async function ao(e,t){let n=N.join(e,"packages","iam","auth");if(!G.existsSync(n))return;if(t==="none"){V(n),Ws(e,`
276
276
  ## Auth
277
277
 
278
278
  Auth was skipped at scaffold time (\`--auth=none\`). Add your preferred auth provider manually (e.g. Clerk, Better Auth, NextAuth, Supabase).
279
- `);return}let o=N.join(n,"src","providers"),r=N.join(n,"src","types.ts");if(t==="clerk"){V(N.join(o,"better-auth.ts")),V(N.join(o,"nextauth.ts")),V(N.join(o,"supabase.ts")),ht(r,"clerk"),St(e,`# Clerk auth
279
+ `);return}let o=N.join(n,"src","providers"),r=N.join(n,"src","types.ts");if(t==="clerk"){V(N.join(o,"better-auth.ts")),V(N.join(o,"nextauth.ts")),V(N.join(o,"supabase.ts")),_t(r,"clerk"),bt(e,`# Clerk auth
280
280
  CLERK_PUBLISHABLE_KEY=
281
281
  CLERK_SECRET_KEY=
282
- `);return}if(t==="betterauth"){V(N.join(o,"clerk.ts")),V(N.join(o,"nextauth.ts")),V(N.join(o,"supabase.ts")),ht(r,"better-auth"),St(e,`# Better Auth
282
+ `);return}if(t==="betterauth"){V(N.join(o,"clerk.ts")),V(N.join(o,"nextauth.ts")),V(N.join(o,"supabase.ts")),_t(r,"better-auth"),bt(e,`# Better Auth
283
283
  BETTER_AUTH_SECRET=
284
284
  BETTER_AUTH_URL=http://localhost:3000
285
- `);return}if(t==="nextauth"){V(N.join(o,"clerk.ts")),V(N.join(o,"better-auth.ts")),V(N.join(o,"supabase.ts")),ht(r,"nextauth"),St(e,`# NextAuth (Auth.js v5)
285
+ `);return}if(t==="nextauth"){V(N.join(o,"clerk.ts")),V(N.join(o,"better-auth.ts")),V(N.join(o,"supabase.ts")),_t(r,"nextauth"),bt(e,`# NextAuth (Auth.js v5)
286
286
  AUTH_SECRET=
287
287
  NEXTAUTH_URL=http://localhost:3000
288
288
  # OAuth (optional \u2014 leave blank to disable that provider)
@@ -290,7 +290,7 @@ GOOGLE_CLIENT_ID=
290
290
  GOOGLE_CLIENT_SECRET=
291
291
  GITHUB_CLIENT_ID=
292
292
  GITHUB_CLIENT_SECRET=
293
- `);return}if(t==="supabase"){V(N.join(o,"clerk.ts")),V(N.join(o,"better-auth.ts")),V(N.join(o,"nextauth.ts")),ht(r,"supabase"),St(e,`# Supabase Auth
293
+ `);return}if(t==="supabase"){V(N.join(o,"clerk.ts")),V(N.join(o,"better-auth.ts")),V(N.join(o,"nextauth.ts")),_t(r,"supabase"),bt(e,`# Supabase Auth
294
294
  NEXT_PUBLIC_SUPABASE_URL=
295
295
  NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=
296
296
  NEXT_PUBLIC_SUPABASE_ANON_KEY=
@@ -298,7 +298,7 @@ SUPABASE_URL=
298
298
  SUPABASE_PUBLISHABLE_KEY=
299
299
  SUPABASE_ANON_KEY=
300
300
  SUPABASE_SERVICE_ROLE_KEY=
301
- `);return}}import xe from"fs";import Ce from"path";function js(e,t){let n=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
301
+ `);return}}import Ne from"fs";import ke from"path";function Xs(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 Bs(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 to(e){xe.mkdirSync(e,{recursive:!0})}function Vs(e,t){let n=Ce.join(e,".env.example");xe.existsSync(n)?xe.appendFileSync(n,`
470
- `+t):xe.writeFileSync(n,t)}function $s(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,n=e.envVars.map(o=>`${o}=`).join(`
469
+ `}function co(e){Ne.mkdirSync(e,{recursive:!0})}function Js(e,t){let n=ke.join(e,".env.example");Ne.existsSync(n)?Ne.appendFileSync(n,`
470
+ `+t):Ne.writeFileSync(n,t)}function Qs(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 no(e,t,n){if(!t||t.length===0)return;let o=Ce.join(e,"apps","web");if(!xe.existsSync(o))return;let r=new Set,s=[];for(let p of t){if(r.has(p))continue;r.add(p);let u=Mn(p);u&&s.push(u)}if(s.length===0)return;for(let p of s)Vs(e,$s(p));let i=Ce.join(o,"src","app","api","auth","callback");for(let p of s){let u=Ce.join(i,p.id);to(u);let d=Ce.join(u,"route.ts");xe.writeFileSync(d,js(p,n))}let a=Ce.join(o,"src","components","auth");to(a);let c=Ce.join(a,"SocialLoginButtons.tsx");xe.writeFileSync(c,Bs(s))}import Je from"fs";import ro from"path";var Et=[{id:"upstash-redis",name:"Upstash Redis",region:"both",envVars:["UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN"],docs:"https://upstash.com/docs/redis",description:"Serverless Redis"},{id:"vercel-kv",name:"Vercel KV",region:"global",envVars:["KV_URL","KV_REST_API_URL","KV_REST_API_TOKEN","KV_REST_API_READ_ONLY_TOKEN"],docs:"https://vercel.com/docs/storage/vercel-kv",description:"Vercel native KV"},{id:"redis",name:"Redis (self-hosted)",region:"both",envVars:["REDIS_URL"],docs:"https://redis.io/docs/",description:"Self-hosted Redis"},{id:"dragonfly",name:"Dragonfly",region:"global",envVars:["DRAGONFLY_URL"],docs:"https://www.dragonflydb.io/docs",description:"Drop-in Redis replacement, faster"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip cache package"}];function oo(e){return Et.find(t=>t.id===e)}var Jp=Et.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import ne from"fs";import vt from"path";function oe(e,t){let n=vt.join(e,".env.example");if(!ne.existsSync(n)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(ne.readFileSync(n,"utf-8").includes(r))return;let a=["","# =============================================",r,t.docs?`# Docs: ${t.docs}`:null,"# =============================================",...t.envVars.map(c=>`${c}=""`),""].filter(c=>c!==null).join(`
474
- `);ne.appendFileSync(n,a)}function re(e,t,n){let o=vt.join(e,".env.example");if(!ne.existsSync(o))return;let r=ne.readFileSync(o,"utf-8"),s=`${t}="${n}"`,i=new RegExp(`^${t}=.*$`,"m");if(i.test(r)){ne.writeFileSync(o,r.replace(i,s));return}let a=r.endsWith(`
473
+ `}async function po(e,t,n){if(!t||t.length===0)return;let o=ke.join(e,"apps","web");if(!Ne.existsSync(o))return;let r=new Set,s=[];for(let p of t){if(r.has(p))continue;r.add(p);let d=Yn(p);d&&s.push(d)}if(s.length===0)return;for(let p of s)Js(e,Qs(p));let i=ke.join(o,"src","app","api","auth","callback");for(let p of s){let d=ke.join(i,p.id);co(d);let m=ke.join(d,"route.ts");Ne.writeFileSync(m,Xs(p,n))}let a=ke.join(o,"src","components","auth");co(a);let c=ke.join(a,"SocialLoginButtons.tsx");Ne.writeFileSync(c,zs(s))}import et from"fs";import uo from"path";var Pt=[{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 lo(e){return Pt.find(t=>t.id===e)}var pl=Pt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import oe from"fs";import wt from"path";function re(e,t){let n=wt.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
+ `);oe.appendFileSync(n,a)}function se(e,t,n){let o=wt.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
- `;ne.appendFileSync(o,`${a}${s}
477
- `)}var Ks=["design","iam","commerce","integrations","platform","ops","ai"];function Re(e,t){for(let o of Ks){let r=vt.join(e,"packages",o,t);if(ne.existsSync(r))return r}let n=vt.join(e,"packages",t);return ne.existsSync(n)?n:null}function z(e,t){let n=Re(e,t);n&&ne.rmSync(n,{recursive:!0,force:!0})}function so(e){return Je.existsSync(e)?Je.readFileSync(e,"utf-8"):null}function Ys(e,t){let n=ro.join(e,".env.example"),o=so(n);if(o===null)return;let r=`# Cache: ${t.name}`;if(o.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
478
- `);Je.appendFileSync(n,s)}function qs(e,t,n){let o=ro.join(e,".env.example"),r=so(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?Je.writeFileSync(o,r.replace(s,`${t}="${n}"`)):Je.appendFileSync(o,`${t}="${n}"
479
- `)}async function io(e,t,n){let o=Re(e,"cache");if(t==="none"){o&&Je.rmSync(o,{recursive:!0,force:!0});return}let r=oo(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${Et.map(s=>s.id).join(", ")}`);o&&(Ys(e,r),qs(e,"CACHE_PROVIDER",t))}var bt=[{id:"turnstile",name:"Cloudflare Turnstile",region:"global",envVars:["NEXT_PUBLIC_TURNSTILE_SITE_KEY","TURNSTILE_SECRET_KEY"],docs:"https://developers.cloudflare.com/turnstile/",description:"Free, privacy-focused captcha alternative"},{id:"hcaptcha",name:"hCaptcha",region:"global",envVars:["NEXT_PUBLIC_HCAPTCHA_SITE_KEY","HCAPTCHA_SECRET_KEY"],docs:"https://docs.hcaptcha.com/",description:"Privacy-respecting captcha"},{id:"aliyun-slide",name:"\u963F\u91CC\u4E91\u9A8C\u8BC1\u7801 2.0",region:"cn",envVars:["ALIYUN_CAPTCHA_ACCESS_KEY_ID","ALIYUN_CAPTCHA_ACCESS_KEY_SECRET","ALIYUN_CAPTCHA_APP_KEY","NEXT_PUBLIC_ALIYUN_CAPTCHA_APP_KEY"],docs:"https://help.aliyun.com/product/28308.html",description:"\u963F\u91CC\u4E91\u667A\u80FD\u9A8C\u8BC1 (\u6ED1\u5757/\u65E0\u75D5)"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function ao(e){return bt.find(t=>t.id===e)}var al=bt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function co(e,t,n="global"){let o=ao(t);if(!o)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${bt.map(r=>r.id).join(", ")}`);if(o.id==="none"){z(e,"captcha");return}o.envVars.length>0&&oe(e,{category:"Captcha",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"CAPTCHA_PROVIDER",o.id)}import Pt from"fs";import Gs from"path";var _t=[{id:"sanity",name:"Sanity",region:"global",envVars:["SANITY_PROJECT_ID","SANITY_DATASET","SANITY_API_TOKEN","SANITY_API_VERSION"],docs:"https://www.sanity.io/docs",description:"Structured content platform with Studio"},{id:"contentful",name:"Contentful",region:"global",envVars:["CONTENTFUL_SPACE_ID","CONTENTFUL_ACCESS_TOKEN","CONTENTFUL_PREVIEW_ACCESS_TOKEN"],docs:"https://www.contentful.com/developers/docs/",description:"Headless CMS"},{id:"strapi",name:"Strapi",region:"both",envVars:["STRAPI_URL","STRAPI_API_TOKEN"],docs:"https://docs.strapi.io",description:"Open-source self-hosted CMS"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function po(e){return _t.find(t=>t.id===e)}var ul=_t.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function lo(e,t,n="global"){let o=po(t);if(!o)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${_t.map(s=>s.id).join(", ")}`);let r=Gs.join(e,"apps","studio");if(o.id==="none"){z(e,"sanity"),Pt.existsSync(r)&&Pt.rmSync(r,{recursive:!0,force:!0});return}o.id!=="sanity"&&(z(e,"sanity"),Pt.existsSync(r)&&Pt.rmSync(r,{recursive:!0,force:!0})),o.envVars.length>0&&oe(e,{category:"CMS",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"CMS_PROVIDER",o.id)}import U from"fs";import O from"path";var Hs=O.join("apps","web"),sn=O.join("src","components","compliance"),at=O.join("src","app","[locale]");function se(e){return O.join(e,Hs)}function Ws(e){U.mkdirSync(e,{recursive:!0})}function J(e,t){Ws(O.dirname(e)),U.writeFileSync(e,t,"utf8")}function an(e,t){let n=O.join(e,".env.example");if(U.existsSync(n)){if(U.readFileSync(n,"utf8").includes(t.split(`
476
+ `;oe.appendFileSync(o,`${a}${s}
477
+ `)}var Zs=["design","iam","commerce","integrations","platform","ops","ai"];function Oe(e,t){for(let o of Zs){let r=wt.join(e,"packages",o,t);if(oe.existsSync(r))return r}let n=wt.join(e,"packages",t);return oe.existsSync(n)?n:null}function J(e,t){let n=Oe(e,t);n&&oe.rmSync(n,{recursive:!0,force:!0})}function mo(e){return et.existsSync(e)?et.readFileSync(e,"utf-8"):null}function ei(e,t){let n=uo.join(e,".env.example"),o=mo(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
+ `);et.appendFileSync(n,s)}function ti(e,t,n){let o=uo.join(e,".env.example"),r=mo(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?et.writeFileSync(o,r.replace(s,`${t}="${n}"`)):et.appendFileSync(o,`${t}="${n}"
479
+ `)}async function go(e,t,n){let o=Oe(e,"cache");if(t==="none"){o&&et.rmSync(o,{recursive:!0,force:!0});return}let r=lo(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${Pt.map(s=>s.id).join(", ")}`);o&&(ei(e,r),ti(e,"CACHE_PROVIDER",t))}var At=[{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 fo(e){return At.find(t=>t.id===e)}var El=At.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function yo(e,t,n="global"){let o=fo(t);if(!o)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${At.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 It from"fs";import ni from"path";var Ct=[{id:"sanity",name:"Sanity",region:"global",envVars:["SANITY_PROJECT_ID","SANITY_DATASET","SANITY_API_TOKEN","SANITY_API_VERSION"],docs:"https://www.sanity.io/docs",description:"Structured content platform with Studio"},{id:"contentful",name:"Contentful",region:"global",envVars:["CONTENTFUL_SPACE_ID","CONTENTFUL_ACCESS_TOKEN","CONTENTFUL_PREVIEW_ACCESS_TOKEN"],docs:"https://www.contentful.com/developers/docs/",description:"Headless CMS"},{id:"strapi",name:"Strapi",region:"both",envVars:["STRAPI_URL","STRAPI_API_TOKEN"],docs:"https://docs.strapi.io",description:"Open-source self-hosted CMS"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function So(e){return Ct.find(t=>t.id===e)}var wl=Ct.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 CMS provider "${t}". Valid ids: ${Ct.map(s=>s.id).join(", ")}`);let r=ni.join(e,"apps","studio");if(o.id==="none"){J(e,"sanity"),It.existsSync(r)&&It.rmSync(r,{recursive:!0,force:!0});return}o.id!=="sanity"&&(J(e,"sanity"),It.existsSync(r)&&It.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 O from"path";var oi=O.join("apps","web"),ln=O.join("src","components","compliance"),dt=O.join("src","app","[locale]");function ie(e){return O.join(e,oi)}function ri(e){U.mkdirSync(e,{recursive:!0})}function Q(e,t){ri(O.dirname(e)),U.writeFileSync(e,t,"utf8")}function dn(e,t){let n=O.join(e,".env.example");if(U.existsSync(n)){if(U.readFileSync(n,"utf8").includes(t.split(`
480
480
  `)[0]??""))return;U.appendFileSync(n,`
481
481
  `+t+`
482
482
  `)}else U.writeFileSync(n,t+`
483
- `)}var ct=`> **TEMPLATE \u2014 NOT LEGAL ADVICE.** This document is a boilerplate scaffold only.
483
+ `)}var ut=`> **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`,Xs=`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`,si=`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
- `,zs=`export function IcpFooter() {
536
+ `,ii=`export function IcpFooter() {
537
537
  const icp = process.env.NEXT_PUBLIC_ICP_BEIAN;
538
538
  if (!icp) return null;
539
539
  return (
@@ -547,7 +547,7 @@ export function Footer({ region = "global" }: FooterProps) {
547
547
  </a>
548
548
  );
549
549
  }
550
- `,Js=`export function PublicSecurityFooter() {
550
+ `,ai=`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
- `,Qs=`"use client";
567
+ `,ci=`"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
- `,Zs=`interface AigcDisclaimerProps {
721
+ `,pi=`interface AigcDisclaimerProps {
722
722
  className?: string;
723
723
  }
724
724
 
@@ -738,13 +738,13 @@ export function AigcDisclaimer({ className }: AigcDisclaimerProps) {
738
738
  </div>
739
739
  );
740
740
  }
741
- `,ei=`---
741
+ `,li=`---
742
742
  title: Privacy Policy / \u9690\u79C1\u653F\u7B56
743
743
  description: How {{COMPANY_NAME}} collects, uses, shares, and protects personal information.
744
744
  lastUpdated: 2026-01-01
745
745
  ---
746
746
 
747
- ${ct}
747
+ ${ut}
748
748
 
749
749
  # Privacy Policy / \u9690\u79C1\u653F\u7B56
750
750
 
@@ -883,13 +883,13 @@ or in-app notification before the change takes effect.
883
883
  **Data Controller / \u6570\u636E\u63A7\u5236\u8005:** {{COMPANY_NAME}}
884
884
  **Address / \u5730\u5740:** {{COMPANY_ADDRESS}}
885
885
  **Email / \u90AE\u7BB1:** {{COMPANY_CONTACT_EMAIL}}
886
- `,ti=`---
886
+ `,di=`---
887
887
  title: Terms of Service / \u670D\u52A1\u6761\u6B3E
888
888
  description: Terms governing your use of {{COMPANY_NAME}}.
889
889
  lastUpdated: 2026-01-01
890
890
  ---
891
891
 
892
- ${ct}
892
+ ${ut}
893
893
 
894
894
  # Terms of Service / \u670D\u52A1\u6761\u6B3E
895
895
 
@@ -1002,13 +1002,13 @@ conflict-of-laws principles. Disputes shall be resolved in the competent courts
1002
1002
  ## 11. Contact / \u8054\u7CFB\u65B9\u5F0F
1003
1003
 
1004
1004
  {{COMPANY_NAME}} \xB7 {{COMPANY_ADDRESS}} \xB7 {{COMPANY_CONTACT_EMAIL}}
1005
- `,ni=`---
1005
+ `,ui=`---
1006
1006
  title: AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
1007
1007
  description: Disclosure required by \u7F51\u4FE1\u529E\u300A\u751F\u6210\u5F0F\u4EBA\u5DE5\u667A\u80FD\u670D\u52A1\u7BA1\u7406\u6682\u884C\u529E\u6CD5\u300B
1008
1008
  lastUpdated: 2026-01-01
1009
1009
  ---
1010
1010
 
1011
- ${ct}
1011
+ ${ut}
1012
1012
 
1013
1013
  # AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
1014
1014
 
@@ -1084,13 +1084,13 @@ human professional.
1084
1084
 
1085
1085
  AI \u8F93\u51FA\u53EF\u80FD\u4E0D\u51C6\u786E\u3001\u5B58\u5728\u504F\u89C1\u6216\u8FC7\u65F6\u3002**\u8BF7\u52FF**\u5728\u672A\u7ECF\u5408\u683C\u4E13\u4E1A\u4EBA\u58EB\u72EC\u7ACB\u6838\u5B9E\u7684\u60C5\u51B5\u4E0B\uFF0C\u5C06 AI \u8F93\u51FA
1086
1086
  \u7528\u4E8E\u533B\u7597\u3001\u6CD5\u5F8B\u3001\u91D1\u878D\u6216\u5B89\u5168\u6538\u5173\u7684\u51B3\u7B56\u3002
1087
- `,oi=`---
1087
+ `,mi=`---
1088
1088
  title: Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
1089
1089
  description: Notice of cross-border transfer of personal information, per PIPL.
1090
1090
  lastUpdated: 2026-01-01
1091
1091
  ---
1092
1092
 
1093
- ${ct}
1093
+ ${ut}
1094
1094
 
1095
1095
  # Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
1096
1096
 
@@ -1149,13 +1149,13 @@ Refusal may limit your ability to use features that rely on overseas services.
1149
1149
  - \u4F20\u8F93\u4E2D\u52A0\u5BC6 (TLS 1.2+) \u53CA\u9759\u6001\u52A0\u5BC6 (AES-256)\u3002
1150
1150
  - \u5408\u540C\u6761\u6B3E\u8981\u6C42\u5883\u5916\u63A5\u6536\u65B9\u63D0\u4F9B\u7B49\u540C\u4E8E PIPL \u7684\u4FDD\u62A4\u3002
1151
1151
  - \u8BBF\u95EE\u63A7\u5236\u3001\u5BA1\u8BA1\u65E5\u5FD7\u548C\u8FDD\u89C4\u901A\u77E5\u7A0B\u5E8F\u3002
1152
- `,ri=`---
1152
+ `,gi=`---
1153
1153
  title: Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
1154
1154
  description: Itemized list of personal information collected, per PIPL Article 17.
1155
1155
  lastUpdated: 2026-01-01
1156
1156
  ---
1157
1157
 
1158
- ${ct}
1158
+ ${ut}
1159
1159
 
1160
1160
  # Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
1161
1161
 
@@ -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=se(e);if(!U.existsSync(n))return;let o=O.join(n,"src","components","compliance","Footer.tsx");J(o,Xs);let r=O.join(n,"src","components","compliance","README.md");J(r,["# Compliance Components","",`Auto-generated by \`create-sailor\` for region: \`${t}\`.`,"","## Mounting the Footer","","```tsx",'import { Footer } from "@/components/compliance/Footer";','import { CookieBanner } from "@/components/compliance/CookieBanner";',"","export default function RootLayout({ children }) {"," return ("," <html>"," <body>"," {children}",` <Footer region="${t}" />`," <CookieBanner />"," </body>"," </html>"," );","}","```","","## Placeholders","","Policy MDX files contain `{{COMPANY_NAME}}`, `{{COMPANY_ADDRESS}}`,","`{{COMPANY_CONTACT_EMAIL}}`, `{{GOVERNING_JURISDICTION}}`, and","`{{AIGC_ALGORITHM_FILING_NUMBER}}`. These are filled by the `brand-apply` step.",""].join(`
1195
- `))}async function ii(e,t){let n=se(e);if(!U.existsSync(n))return;let o=O.join(n,"src","components","compliance","CookieBanner.tsx");J(o,Qs)}async function ai(e,t){let n=se(e);if(!U.existsSync(n))return;let o=O.join(n,at,"privacy","page.mdx");J(o,ei)}async function ci(e,t){let n=se(e);if(!U.existsSync(n))return;let o=O.join(n,at,"terms","page.mdx");J(o,ti)}async function pi(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,sn,"IcpFooter.tsx");J(n,zs),an(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 li(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,sn,"PublicSecurityFooter.tsx");J(n,Js),an(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 di(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,sn,"AigcDisclaimer.tsx");J(n,Zs),an(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 ui(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,at,"aigc-disclosure","page.mdx");J(n,ni)}async function mi(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,at,"cross-border-data","page.mdx");J(n,oi)}async function gi(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,at,"pii-collection","page.mdx");J(n,ri)}async function uo(e,t){try{await si(e,t),await ii(e,t),await ai(e,t),await ci(e,t),(t==="cn"||t==="hybrid")&&(await pi(e),await li(e),await di(e),await ui(e),await mi(e),await gi(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 fi from"fs";import yi from"path";async function mo(e,t){let n=yi.join(e,"nebutra.config.json");fi.writeFileSync(n,JSON.stringify(t,null,2)+`
1199
- `)}import R from"fs";import Te from"path";function Si(e){R.existsSync(e)&&R.rmSync(e,{recursive:!0,force:!0})}function go(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function hi(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function fo(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 Ei(e,t){let n=Te.join(e,".env.example");R.existsSync(n)?R.appendFileSync(n,`
1200
- `+t):R.writeFileSync(n,t)}async function yo(e,t,n){let o=Te.join(e,"packages","platform","db");if(t==="none"){Si(o);return}let r=Te.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",Ei(e,`# Database (${t})
1194
+ `;async function fi(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=O.join(n,"src","components","compliance","Footer.tsx");Q(o,si);let r=O.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 yi(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=O.join(n,"src","components","compliance","CookieBanner.tsx");Q(o,ci)}async function Si(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=O.join(n,dt,"privacy","page.mdx");Q(o,li)}async function hi(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=O.join(n,dt,"terms","page.mdx");Q(o,di)}async function Ei(e){let t=ie(e);if(!U.existsSync(t))return;let n=O.join(t,ln,"IcpFooter.tsx");Q(n,ii),dn(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 vi(e){let t=ie(e);if(!U.existsSync(t))return;let n=O.join(t,ln,"PublicSecurityFooter.tsx");Q(n,ai),dn(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 bi(e){let t=ie(e);if(!U.existsSync(t))return;let n=O.join(t,ln,"AigcDisclaimer.tsx");Q(n,pi),dn(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 _i(e){let t=ie(e);if(!U.existsSync(t))return;let n=O.join(t,dt,"aigc-disclosure","page.mdx");Q(n,ui)}async function Pi(e){let t=ie(e);if(!U.existsSync(t))return;let n=O.join(t,dt,"cross-border-data","page.mdx");Q(n,mi)}async function wi(e){let t=ie(e);if(!U.existsSync(t))return;let n=O.join(t,dt,"pii-collection","page.mdx");Q(n,gi)}async function Eo(e,t){try{await fi(e,t),await yi(e,t),await Si(e,t),await hi(e,t),(t==="cn"||t==="hybrid")&&(await Ei(e),await vi(e),await bi(e),await _i(e),await Pi(e),await wi(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 Ai from"fs";import Ci from"path";async function vo(e,t){let n=Ci.join(e,"nebutra.config.json");Ai.writeFileSync(n,JSON.stringify(t,null,2)+`
1199
+ `)}import R from"fs";import Le from"path";function Ii(e){R.existsSync(e)&&R.rmSync(e,{recursive:!0,force:!0})}function bo(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function xi(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function _o(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 Ri(e,t){let n=Le.join(e,".env.example");R.existsSync(n)?R.appendFileSync(n,`
1200
+ `+t):R.writeFileSync(n,t)}async function Po(e,t,n){let o=Le.join(e,"packages","platform","db");if(t==="none"){Ii(o);return}let r=Le.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",Ri(e,`# Database (${t})
1201
1201
  DATABASE_URL="${s}"
1202
- `),!R.existsSync(r))return;let i=R.readFileSync(r,"utf8"),a=i;t==="mysql"?(a=go(a,"mysql"),a=fo(a)):t==="sqlite"&&(a=go(a,"sqlite"),a=hi(a),a=fo(a)),a!==i&&R.writeFileSync(r,a)}function vi(e){let t=Te.join(e,".env.example");return R.existsSync(t)?R.readFileSync(t,"utf8"):""}function bi(e,t,n,o){let r=Te.join(e,".env.example"),s=vi(e),i=o?`# ${o}
1202
+ `),!R.existsSync(r))return;let i=R.readFileSync(r,"utf8"),a=i;t==="mysql"?(a=bo(a,"mysql"),a=_o(a)):t==="sqlite"&&(a=bo(a,"sqlite"),a=xi(a),a=_o(a)),a!==i&&R.writeFileSync(r,a)}function Ti(e){let t=Le.join(e,".env.example");return R.existsSync(t)?R.readFileSync(t,"utf8"):""}function ki(e,t,n,o){let r=Le.join(e,".env.example"),s=Ti(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)){R.writeFileSync(r,s.replace(a,`${t}="${n}"`));return}s?R.appendFileSync(r,`
1206
- ${i}`):R.writeFileSync(r,i)}function _i(e,t){let n=Te.join(e,"packages","platform","db","prisma","schema.prisma");if(!R.existsSync(n))return;let o=R.readFileSync(n,"utf8"),r=/(datasource\s+db\s*\{[^}]*?)(\n})/;if(!o.match(r))return;let i=t.filter(p=>!o.includes(p.trim()));if(i.length===0)return;let a=i.map(p=>` ${p}`).join(`
1206
+ ${i}`):R.writeFileSync(r,i)}function Ni(e,t){let n=Le.join(e,"packages","platform","db","prisma","schema.prisma");if(!R.existsSync(n))return;let o=R.readFileSync(n,"utf8"),r=/(datasource\s+db\s*\{[^}]*?)(\n})/;if(!o.match(r))return;let i=t.filter(p=>!o.includes(p.trim()));if(i.length===0)return;let a=i.map(p=>` ${p}`).join(`
1207
1207
  `),c=o.replace(r,`$1
1208
- ${a}$2`);R.writeFileSync(n,c)}function Pi(e){let t=Te.join(e,"packages","platform","db","prisma","schema.prisma");if(!R.existsSync(t))return;let n=R.readFileSync(t,"utf8");if(/directUrl\s*=\s*env\(/.test(n))return;let o=/(datasource\s+db\s*\{[\s\S]*?url\s*=\s*env\(\s*"DATABASE_URL"\s*\)[^\n]*\n)/;o.test(n)&&R.writeFileSync(t,n.replace(o,`$1 directUrl = env("DIRECT_URL")
1209
- `))}async function So(e,t,n){if(!(t.id==="none"||t.id==="local")){for(let o of t.envVars){let r=o.placeholder.replace(/\$PROJECT/g,n);bi(e,o.name,r,o.comment)}t.prismaDatasourceExtras&&t.prismaDatasourceExtras.length>0&&_i(e,t.prismaDatasourceExtras),t.keepDirectUrl&&Pi(e)}}import be from"fs";import ke from"path";import{fileURLToPath as wi}from"url";var Ai=wi(import.meta.url),ho=ke.dirname(Ai),Ii=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,Eo=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function Ci(e){let t=[ke.join(ho,"..","templates","docs",e),ke.join(ho,"..","..","templates","docs",e)];for(let n of t)if(be.existsSync(n))return n;return t[0]}async function vo(e,t){if(t.framework==="none")return;if(!Eo.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${Eo.join(", ")}, none.`);let n=Ci(t.framework),o=ke.join(e,"apps","docs");if(!be.existsSync(n))throw new Error(`Docs template not found: ${n}`);bo(n,o),_o(o,{"{PRODUCT_NAME}":t.projectName})}function bo(e,t){be.mkdirSync(t,{recursive:!0});for(let n of be.readdirSync(e,{withFileTypes:!0})){let o=ke.join(e,n.name),r=ke.join(t,n.name);n.isDirectory()?bo(o,r):be.copyFileSync(o,r)}}function _o(e,t){for(let n of be.readdirSync(e,{withFileTypes:!0})){let o=ke.join(e,n.name);if(n.isDirectory())_o(o,t);else if(Ii.test(n.name)){let r=be.readFileSync(o,"utf-8");for(let[s,i]of Object.entries(t))r=r.split(s).join(i);be.writeFileSync(o,r)}}}import Oe from"fs";import Ne from"path";var wt=[{id:"resend",name:"Resend",region:"global",envVars:["RESEND_API_KEY","RESEND_FROM"],docs:"https://resend.com/docs",pkg:"resend",pkgVersion:"^4.0.1"},{id:"postmark",name:"Postmark",region:"global",envVars:["POSTMARK_API_KEY","POSTMARK_FROM"],docs:"https://postmarkapp.com/developer",pkg:"postmark",pkgVersion:"^4.0.5"},{id:"ses",name:"AWS SES",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_SES_REGION","SES_FROM"],docs:"https://docs.aws.amazon.com/ses",pkg:"@aws-sdk/client-sesv2",pkgVersion:"^3.658.0"},{id:"aliyun-dm",name:"\u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001",region:"cn",envVars:["ALIYUN_DM_ACCESS_KEY","ALIYUN_DM_ACCESS_SECRET","ALIYUN_DM_ACCOUNT_NAME","ALIYUN_DM_FROM_ALIAS"],docs:"https://help.aliyun.com/product/29412.html",pkg:"@alicloud/dm20151123",pkgVersion:"^3.0.0"},{id:"tencent-ses",name:"\u817E\u8BAF\u4E91 SES",region:"cn",envVars:["TENCENT_SECRET_ID","TENCENT_SECRET_KEY","TENCENT_SES_FROM_EMAIL"],docs:"https://cloud.tencent.com/document/product/1288",pkg:"tencentcloud-sdk-nodejs-ses",pkgVersion:"^4.0.900"},{id:"netease",name:"\u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1",region:"cn",envVars:["NETEASE_USER","NETEASE_PASS","NETEASE_FROM"],docs:"https://qiye.163.com/help",pkg:"nodemailer",pkgVersion:"^6.9.15"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function Po(e){return wt.find(t=>t.id===e)}var Ol=wt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Le="@nebutra/email";function cn(e,t){Oe.mkdirSync(Ne.dirname(e),{recursive:!0}),Oe.writeFileSync(e,t)}function xi(e,t){let n=Ne.join(e,".env.example");Oe.existsSync(n)?Oe.appendFileSync(n,`
1210
- `+t):Oe.writeFileSync(n,t)}function Ri(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
1208
+ ${a}$2`);R.writeFileSync(n,c)}function Oi(e){let t=Le.join(e,"packages","platform","db","prisma","schema.prisma");if(!R.existsSync(t))return;let n=R.readFileSync(t,"utf8");if(/directUrl\s*=\s*env\(/.test(n))return;let o=/(datasource\s+db\s*\{[\s\S]*?url\s*=\s*env\(\s*"DATABASE_URL"\s*\)[^\n]*\n)/;o.test(n)&&R.writeFileSync(t,n.replace(o,`$1 directUrl = env("DIRECT_URL")
1209
+ `))}async function wo(e,t,n){if(!(t.id==="none"||t.id==="local")){for(let o of t.envVars){let r=o.placeholder.replace(/\$PROJECT/g,n);ki(e,o.name,r,o.comment)}t.prismaDatasourceExtras&&t.prismaDatasourceExtras.length>0&&Ni(e,t.prismaDatasourceExtras),t.keepDirectUrl&&Oi(e)}}import we from"fs";import Ue from"path";import{fileURLToPath as Li}from"url";var Ui=Li(import.meta.url),Ao=Ue.dirname(Ui),Di=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,Co=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function Mi(e){let t=[Ue.join(Ao,"..","templates","docs",e),Ue.join(Ao,"..","..","templates","docs",e)];for(let n of t)if(we.existsSync(n))return n;return t[0]}async function Io(e,t){if(t.framework==="none")return;if(!Co.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${Co.join(", ")}, none.`);let n=Mi(t.framework),o=Ue.join(e,"apps","docs");if(!we.existsSync(n))throw new Error(`Docs template not found: ${n}`);xo(n,o),Ro(o,{"{PRODUCT_NAME}":t.projectName})}function xo(e,t){we.mkdirSync(t,{recursive:!0});for(let n of we.readdirSync(e,{withFileTypes:!0})){let o=Ue.join(e,n.name),r=Ue.join(t,n.name);n.isDirectory()?xo(o,r):we.copyFileSync(o,r)}}function Ro(e,t){for(let n of we.readdirSync(e,{withFileTypes:!0})){let o=Ue.join(e,n.name);if(n.isDirectory())Ro(o,t);else if(Di.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 Me from"fs";import De from"path";var xt=[{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 To(e){return xt.find(t=>t.id===e)}var ql=xt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Fe="@nebutra/email";function un(e,t){Me.mkdirSync(De.dirname(e),{recursive:!0}),Me.writeFileSync(e,t)}function Fi(e,t){let n=De.join(e,".env.example");Me.existsSync(n)?Me.appendFileSync(n,`
1210
+ `+t):Me.writeFileSync(n,t)}function ji(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 Ti=`/**
1213
+ `}var Bi=`/**
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,8 +1230,8 @@ 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`/**
1234
- * @${Le.slice(1)} \u2014 Resend transactional email wrapper.
1233
+ `;function $i(){return`/**
1234
+ * @${Fe.slice(1)} \u2014 Resend transactional email wrapper.
1235
1235
  *
1236
1236
  * Docs: https://resend.com/docs
1237
1237
  */
@@ -1269,8 +1269,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1269
1269
  }
1270
1270
 
1271
1271
  export type { SendEmailInput, SendEmailResult } from "./types";
1272
- `}function Ni(){return`/**
1273
- * @${Le.slice(1)} \u2014 Postmark transactional email wrapper.
1272
+ `}function Vi(){return`/**
1273
+ * @${Fe.slice(1)} \u2014 Postmark transactional email wrapper.
1274
1274
  *
1275
1275
  * Docs: https://postmarkapp.com/developer
1276
1276
  */
@@ -1307,8 +1307,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1307
1307
  }
1308
1308
 
1309
1309
  export type { SendEmailInput, SendEmailResult } from "./types";
1310
- `}function Oi(){return`/**
1311
- * @${Le.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1310
+ `}function Ki(){return`/**
1311
+ * @${Fe.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1312
1312
  *
1313
1313
  * Docs: https://docs.aws.amazon.com/ses
1314
1314
  */
@@ -1363,8 +1363,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1363
1363
  }
1364
1364
 
1365
1365
  export type { SendEmailInput, SendEmailResult } from "./types";
1366
- `}function Li(){return`/**
1367
- * @${Le.slice(1)} \u2014 \u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001 (Aliyun DirectMail) wrapper.
1366
+ `}function Yi(){return`/**
1367
+ * @${Fe.slice(1)} \u2014 \u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001 (Aliyun DirectMail) wrapper.
1368
1368
  *
1369
1369
  * Docs: https://help.aliyun.com/product/29412.html
1370
1370
  */
@@ -1413,8 +1413,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1413
1413
  }
1414
1414
 
1415
1415
  export type { SendEmailInput, SendEmailResult } from "./types";
1416
- `}function Ui(){return`/**
1417
- * @${Le.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1416
+ `}function qi(){return`/**
1417
+ * @${Fe.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1418
1418
  *
1419
1419
  * Docs: https://cloud.tencent.com/document/product/1288
1420
1420
  */
@@ -1461,8 +1461,8 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
1461
1461
  }
1462
1462
 
1463
1463
  export type { SendEmailInput, SendEmailResult } from "./types";
1464
- `}function Di(){return`/**
1465
- * @${Le.slice(1)} \u2014 \u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1 via SMTP (nodemailer).
1464
+ `}function Gi(){return`/**
1465
+ * @${Fe.slice(1)} \u2014 \u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1 via SMTP (nodemailer).
1466
1466
  *
1467
1467
  * Docs: https://qiye.163.com/help
1468
1468
  */
@@ -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 Mi(e){switch(e){case"resend":return ki();case"postmark":return Ni();case"ses":return Oi();case"aliyun-dm":return Li();case"tencent-ses":return Ui();case"netease":return Di();case"none":return`export {};
1503
- `}}function Fi(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),e.id==="aliyun-dm"&&(t["@alicloud/openapi-client"]="^0.4.12");let n={name:Le,version:"0.1.0",private:!0,description:`Transactional email via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
1504
- `}async function wo(e,t,n){if(t==="none")return;let o=Po(t);if(!o)throw new Error(`Unknown email provider "${t}". Valid ids: ${wt.map(i=>i.id).join(", ")}`);let r=Ne.join(e,"packages","email"),s=Ne.join(r,"src");Oe.existsSync(s)&&Oe.rmSync(s,{recursive:!0,force:!0}),cn(Ne.join(r,"package.json"),Fi(o)),cn(Ne.join(s,"types.ts"),Ti),cn(Ne.join(s,"index.ts"),Mi(o.id)),xi(e,Ri(o))}import de from"fs";import Ao from"path";function ji(e,t){return new RegExp(`^\\s*${t}\\s*=`,"m").test(e)}function Io(e){return e.endsWith(`
1502
+ `}function Hi(e){switch(e){case"resend":return $i();case"postmark":return Vi();case"ses":return Ki();case"aliyun-dm":return Yi();case"tencent-ses":return qi();case"netease":return Gi();case"none":return`export {};
1503
+ `}}function Wi(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:Fe,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 ko(e,t,n){if(t==="none")return;let o=To(t);if(!o)throw new Error(`Unknown email provider "${t}". Valid ids: ${xt.map(i=>i.id).join(", ")}`);let r=De.join(e,"packages","email"),s=De.join(r,"src");Me.existsSync(s)&&Me.rmSync(s,{recursive:!0,force:!0}),un(De.join(r,"package.json"),Wi(o)),un(De.join(s,"types.ts"),Bi),un(De.join(s,"index.ts"),Hi(o.id)),Fi(e,ji(o))}import ue from"fs";import No from"path";function Xi(e,t){return new RegExp(`^\\s*${t}\\s*=`,"m").test(e)}function Oo(e){return e.endsWith(`
1505
1505
  `)?e:`${e}
1506
- `}async function Co(e,t){let n=Ao.join(e,".env"),o=Ao.join(e,".env.local"),r=de.existsSync(n)?de.readFileSync(n,"utf8"):"",s=de.existsSync(o)?de.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
1506
+ `}async function Lo(e,t){let n=No.join(e,".env"),o=No.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=>!Xi(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
- `;try{let p=de.readFileSync(o,"utf8"),u=Io(p);de.writeFileSync(o,`${u}
1511
- ${c}`)}catch{try{de.writeFileSync(o,c,{flag:"wx"})}catch{let p=de.readFileSync(o,"utf8");de.writeFileSync(o,`${Io(p)}
1512
- ${c}`)}}}import Ro from"crypto";import pt from"fs";import xo from"path";function Ue(e){return Ro.randomBytes(e).toString("base64").replace(/=+$/,"")}function Bi(e){return Ro.randomBytes(e).toString("hex")}function Vi(){return{AUTH_SECRET:Ue(32),NEXTAUTH_SECRET:Ue(32),BETTER_AUTH_SECRET:Ue(32),JWT_SECRET:Ue(32),WEBHOOK_SECRET:Bi(16),ENCRYPTION_KEY:Ue(32),API_SECRET_KEY:Ue(32),SESSION_SECRET:Ue(32)}}function $i(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Ki(e,t,n){let o=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=$i(n);return e.replace(o,`${t}="${r}"`)}async function To(e){let t=xo.join(e,".env.example"),n=xo.join(e,".env.local");if(!pt.existsSync(t))return null;try{let o=pt.readFileSync(t,"utf8"),r=Vi(),i=pt.existsSync(n)?pt.readFileSync(n,"utf8"):o;for(let a of Object.keys(r))i=Ki(i,a,r[a]);return pt.writeFileSync(n,i),r}catch(o){let r=o instanceof Error?o.message:String(o);throw console.error(`[create-sailor] Failed to generate env secrets: ${r}`),new Error(`Unable to write .env.local: ${r}`)}}var At=[{id:"vercel-flags",name:"Vercel Flags SDK",region:"global",envVars:["FLAGS_SECRET"],docs:"https://vercel.com/docs/workflow-collaboration/feature-flags",description:"Native Vercel feature flags"},{id:"growthbook",name:"GrowthBook",region:"both",envVars:["GROWTHBOOK_API_HOST","GROWTHBOOK_CLIENT_KEY","GROWTHBOOK_DECRYPTION_KEY"],docs:"https://docs.growthbook.io",description:"Open-source A/B testing + flags"},{id:"configcat",name:"ConfigCat",region:"global",envVars:["CONFIGCAT_SDK_KEY"],docs:"https://configcat.com/docs/",description:"Feature flag & config management"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function ko(e){return At.find(t=>t.id===e)}var Gl=At.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function No(e,t,n="global"){let o=ko(t);if(!o)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${At.map(r=>r.id).join(", ")}`);if(o.id==="none"){z(e,"feature-flags");return}o.envVars.length>0&&oe(e,{category:"Feature Flags",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"FEATURE_FLAGS_PROVIDER",o.id)}import{execFileSync as Do}from"child_process";import L from"fs";import Yi from"os";import ie from"path";import qi from"ignore";var Gi={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 Hi(){let e=process.env.SAILOR_TEMPLATE_LOCAL_DIR;if(!(!e||e.trim().length===0))return ie.resolve(e.trim())}var Wi=new Set(["node_modules",".git","dist",".next",".turbo"]);function Xi(e,t){if(!L.statSync(e).isDirectory())throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR is not a directory: ${e}`);L.cpSync(e,t,{recursive:!0,dereference:!0,filter:o=>{let r=ie.basename(o);return!Wi.has(r)}})}function zi(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function Ji(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function Mo(e){return/^[0-9a-f]{7,40}$/i.test(e)}function Qi(e,t){let n=`https://github.com/${e}.git`,o=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of o)try{let s=Do("git",["ls-remote",n,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!s)continue;let[i]=s.split(/\s+/);if(Mo(i))return i}catch{}return null}async function Zi(e,t){if(Mo(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=Qi(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 Fo(e,t,n){let o=L.readdirSync(t,{withFileTypes:!0});for(let r of o){if(r.name==="node_modules"||r.name===".git")continue;let s=ie.join(t,r.name),i=ie.relative(e,s).split(ie.sep).join("/");r.isDirectory()?(n.push(i+"/"),Fo(e,s,n)):n.push(i)}}function Oo(e){let t=ie.join(e,".templateignore");if(!L.existsSync(t))return;let n=L.readFileSync(t,"utf8"),o=qi().add(n),r=[];Fo(e,e,r);let s=r.map(c=>c.endsWith("/")?c.slice(0,-1):c),i=new Set(o.filter(s)),a=s.filter(c=>!i.has(c)).sort((c,p)=>p.split("/").length-c.split("/").length);for(let c of a){let p=ie.join(e,c);try{L.existsSync(p)&&L.rmSync(p,{recursive:!0,force:!0})}catch{}}try{L.existsSync(t)&&L.rmSync(t,{force:!0})}catch{}}async function Lo(e,t){let n=await fetch(e,{headers:{Accept:"application/octet-stream","User-Agent":"create-sailor"}});if(!n.ok)throw new Error(`Failed to download archive (${n.status})`);let o=Buffer.from(await n.arrayBuffer());if(o.byteLength<1024)throw new Error(`Downloaded archive is unexpectedly small (${o.byteLength} bytes)`);L.writeFileSync(t,o);let r=L.statSync(t);if(r.size!==o.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${o.byteLength})`);return r.size}function Uo(e,t){Do("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function pn(e){try{let t=L.readdirSync(e);for(let n of t)L.rmSync(ie.join(e,n),{recursive:!0,force:!0})}catch{}}async function ea(e,t){let n=L.mkdtempSync(ie.join(Yi.tmpdir(),"create-sailor-")),o=ie.join(n,"template.tar.gz");try{let r=await Zi(e.repo,e.ref);await Lo(Ji(e.repo,r),o),Uo(o,t)}catch(r){if(!e.allowMutableFallback)throw r;pn(t),await Lo(zi(e.repo,e.ref),o),Uo(o,t)}finally{L.rmSync(n,{recursive:!0,force:!0})}}async function jo(e){L.mkdirSync(e,{recursive:!0});let t=Hi();if(t){if(!L.existsSync(t))throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR does not exist: ${t}`);pn(e),Xi(t,e);try{Oo(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=Gi[s];try{if(await ea(i,e),i.applyIgnore)try{Oo(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)),pn(e)}}throw new Error(`Failed to download the template from any source. Last error: ${r?.message??"unknown"}
1510
+ `;try{let p=ue.readFileSync(o,"utf8"),d=Oo(p);ue.writeFileSync(o,`${d}
1511
+ ${c}`)}catch{try{ue.writeFileSync(o,c,{flag:"wx"})}catch{let p=ue.readFileSync(o,"utf8");ue.writeFileSync(o,`${Oo(p)}
1512
+ ${c}`)}}}import Do from"crypto";import mt from"fs";import Uo from"path";function je(e){return Do.randomBytes(e).toString("base64").replace(/=+$/,"")}function zi(e){return Do.randomBytes(e).toString("hex")}function Ji(){return{AUTH_SECRET:je(32),NEXTAUTH_SECRET:je(32),BETTER_AUTH_SECRET:je(32),JWT_SECRET:je(32),WEBHOOK_SECRET:zi(16),ENCRYPTION_KEY:je(32),API_SECRET_KEY:je(32),SESSION_SECRET:je(32)}}function Qi(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Zi(e,t,n){let o=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=Qi(n);return e.replace(o,`${t}="${r}"`)}async function Mo(e){let t=Uo.join(e,".env.example"),n=Uo.join(e,".env.local");if(!mt.existsSync(t))return null;try{let o=mt.readFileSync(t,"utf8"),r=Ji(),i=mt.existsSync(n)?mt.readFileSync(n,"utf8"):o;for(let a of Object.keys(r))i=Zi(i,a,r[a]);return mt.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 Rt=[{id:"vercel-flags",name:"Vercel Flags SDK",region:"global",envVars:["FLAGS_SECRET"],docs:"https://vercel.com/docs/workflow-collaboration/feature-flags",description:"Native Vercel feature flags"},{id:"growthbook",name:"GrowthBook",region:"both",envVars:["GROWTHBOOK_API_HOST","GROWTHBOOK_CLIENT_KEY","GROWTHBOOK_DECRYPTION_KEY"],docs:"https://docs.growthbook.io",description:"Open-source A/B testing + flags"},{id:"configcat",name:"ConfigCat",region:"global",envVars:["CONFIGCAT_SDK_KEY"],docs:"https://configcat.com/docs/",description:"Feature flag & config management"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Fo(e){return Rt.find(t=>t.id===e)}var rd=Rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function jo(e,t,n="global"){let o=Fo(t);if(!o)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${Rt.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 Ko}from"child_process";import L from"fs";import ea from"os";import ae from"path";import ta from"ignore";var na={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 oa(){let e=process.env.SAILOR_TEMPLATE_LOCAL_DIR;if(!(!e||e.trim().length===0))return ae.resolve(e.trim())}var ra=new Set(["node_modules",".git","dist",".next",".turbo"]);function sa(e,t){if(!L.statSync(e).isDirectory())throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR is not a directory: ${e}`);L.cpSync(e,t,{recursive:!0,dereference:!0,filter:o=>{let r=ae.basename(o);return!ra.has(r)}})}function ia(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function aa(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function Yo(e){return/^[0-9a-f]{7,40}$/i.test(e)}function ca(e,t){let n=`https://github.com/${e}.git`,o=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of o)try{let s=Ko("git",["ls-remote",n,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!s)continue;let[i]=s.split(/\s+/);if(Yo(i))return i}catch{}return null}async function pa(e,t){if(Yo(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=ca(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 qo(e,t,n){let o=L.readdirSync(t,{withFileTypes:!0});for(let r of o){if(r.name==="node_modules"||r.name===".git")continue;let s=ae.join(t,r.name),i=ae.relative(e,s).split(ae.sep).join("/");r.isDirectory()?(n.push(i+"/"),qo(e,s,n)):n.push(i)}}function Bo(e){let t=ae.join(e,".templateignore");if(!L.existsSync(t))return;let n=L.readFileSync(t,"utf8"),o=ta().add(n),r=[];qo(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{L.existsSync(p)&&L.rmSync(p,{recursive:!0,force:!0})}catch{}}try{L.existsSync(t)&&L.rmSync(t,{force:!0})}catch{}}async function $o(e,t){let n=await fetch(e,{headers:{Accept:"application/octet-stream","User-Agent":"create-sailor"}});if(!n.ok)throw new Error(`Failed to download archive (${n.status})`);let o=Buffer.from(await n.arrayBuffer());if(o.byteLength<1024)throw new Error(`Downloaded archive is unexpectedly small (${o.byteLength} bytes)`);L.writeFileSync(t,o);let r=L.statSync(t);if(r.size!==o.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${o.byteLength})`);return r.size}function Vo(e,t){Ko("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function mn(e){try{let t=L.readdirSync(e);for(let n of t)L.rmSync(ae.join(e,n),{recursive:!0,force:!0})}catch{}}async function la(e,t){let n=L.mkdtempSync(ae.join(ea.tmpdir(),"create-sailor-")),o=ae.join(n,"template.tar.gz");try{let r=await pa(e.repo,e.ref);await $o(aa(e.repo,r),o),Vo(o,t)}catch(r){if(!e.allowMutableFallback)throw r;mn(t),await $o(ia(e.repo,e.ref),o),Vo(o,t)}finally{L.rmSync(n,{recursive:!0,force:!0})}}async function Go(e){L.mkdirSync(e,{recursive:!0});let t=oa();if(t){if(!L.existsSync(t))throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR does not exist: ${t}`);mn(e),sa(t,e);try{Bo(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=na[s];try{if(await la(i,e),i.applyIgnore)try{Bo(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)),mn(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 It from"fs";import ln from"path";var ta="node scripts/governance/lint-no-raw-inputs.mjs",na="node scripts/governance/lint-repository-seam.mjs",oa="node scripts/governance/lint-brand-literals.mjs",ra="node scripts/governance/lint-microcopy.mjs",sa=/\bnode\s+scripts\/(governance\/)?lint-[\w-]+\.mjs/g,ia=/\bnode\s+scripts\/lint-[\w-]+\.mjs/,aa={scanRoots:["apps"],primitivesImport:"@nebutra/ui/primitives",whitelist:["/storybook/src/stories/","/design-docs/src/components/previews/","/sailor-docs/src/components/previews/","\\.test\\.tsx?$","/__tests__/"]},ca={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"]},pa={scanRoots:["apps/web/src"],excludePaths:["/api/","\\.test\\.tsx?$","/__tests__/","/storybook/src/stories/","/design-docs/","/sailor-docs/"],bannedPatterns:[],allowlist:[]},Bo={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:[]},la=["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 da(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 ua(e){let t=new RegExp(Bo.allowExpressions.join("|"));return la.filter(n=>{try{return t.test(It.readFileSync(ln.join(e,n),"utf8"))}catch{return!1}})}async function Vo(e,t){let n=t.database!=="none",o=[ta];n&&o.push(na),o.push(oa),o.push(ra);let r={...Bo,allowlist:ua(e)},s={rawInputs:aa,brandLiterals:r,microcopyRules:pa};n&&(s.repositorySeam=ca);let i=ln.join(e,"governance.config.json");It.writeFileSync(i,JSON.stringify(s,null,2)+`
1516
- `);let a=ln.join(e,"package.json"),c;try{c=It.readFileSync(a,"utf8")}catch(p){if(p.code!=="ENOENT")throw p}if(c!==void 0){let p=JSON.parse(c);p.scripts=p.scripts??{};for(let[u,d]of Object.entries(p.scripts))u!=="lint"&&typeof d=="string"&&ia.test(d)&&delete p.scripts[u];p.scripts.lint=da(p.scripts.lint,o),It.writeFileSync(a,JSON.stringify(p,null,2)+`
1517
- `)}return{lints:o,configWritten:!0}}import Q from"fs";import ae from"path";import{fileURLToPath as ma}from"url";var ga=ma(import.meta.url),$o=ae.dirname(ga),Ko="scaffold-meta.json",Yo=".nebutra";function fa(e){if(e)return e;let t=[ae.join($o,"..","templates"),ae.join($o,"..","..","templates")];for(let n of t)if(Q.existsSync(n))return n;return t[0]}function qo(e,t){let n=[],o=fa(t.templatesRoot),r=ae.join(e,"LICENSE");if(Q.existsSync(r)){let p=Q.readFileSync(r,"utf-8").slice(0,256);(/GNU AFFERO GENERAL PUBLIC LICENSE/i.test(p)||/Functional Source License/i.test(p))&&(Q.renameSync(r,ae.join(e,"LICENSE-UPSTREAM-REFERENCE.md")),n.push("LICENSE-UPSTREAM-REFERENCE.md (preserved upstream licence)"))}let s=ae.join(o,"LICENSE-SCAFFOLD.md");if(!Q.existsSync(s))throw new Error(`LICENSE-SCAFFOLD.md template missing at ${s}; cannot emit license.`);Q.copyFileSync(s,ae.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=ae.join(e,Yo);Q.mkdirSync(a,{recursive:!0}),Q.writeFileSync(ae.join(a,Ko),`${JSON.stringify(i,null,2)}
1518
- `),n.push(`${Yo}/${Ko}`);let c=ae.join(e,"README.md");if(Q.existsSync(c)){let p=Q.readFileSync(c,"utf-8");p.includes("Scaffolded by `create-sailor`")||(Q.writeFileSync(c,`> **License notice:** Scaffolded by \`create-sailor\`. The Nebutra-Sailor
1515
+ You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import Tt from"fs";import gn from"path";var da="node scripts/governance/lint-no-raw-inputs.mjs",ua="node scripts/governance/lint-repository-seam.mjs",ma="node scripts/governance/lint-brand-literals.mjs",ga="node scripts/governance/lint-microcopy.mjs",fa=/\bnode\s+scripts\/(governance\/)?lint-[\w-]+\.mjs/g,ya=/\bnode\s+scripts\/lint-[\w-]+\.mjs/,Sa={scanRoots:["apps"],primitivesImport:"@nebutra/ui/primitives",whitelist:["/storybook/src/stories/","/design-docs/src/components/previews/","/sailor-docs/src/components/previews/","\\.test\\.tsx?$","/__tests__/"]},ha={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"]},Ea={scanRoots:["apps/web/src"],excludePaths:["/api/","\\.test\\.tsx?$","/__tests__/","/storybook/src/stories/","/design-docs/","/sailor-docs/"],bannedPatterns:[],allowlist:[]},Ho={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:[]},va=["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 ba(e,t){let n=(e??"").replace(fa,"").split("&&").map(r=>r.trim()).filter(Boolean).join(" && ");return[n.length>0?n:"biome check .",...t].join(" && ")}function _a(e){let t=new RegExp(Ho.allowExpressions.join("|"));return va.filter(n=>{try{return t.test(Tt.readFileSync(gn.join(e,n),"utf8"))}catch{return!1}})}async function Wo(e,t){let n=t.database!=="none",o=[da];n&&o.push(ua),o.push(ma),o.push(ga);let r={...Ho,allowlist:_a(e)},s={rawInputs:Sa,brandLiterals:r,microcopyRules:Ea};n&&(s.repositorySeam=ha);let i=gn.join(e,"governance.config.json");Tt.writeFileSync(i,JSON.stringify(s,null,2)+`
1516
+ `);let a=gn.join(e,"package.json"),c;try{c=Tt.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,m]of Object.entries(p.scripts))d!=="lint"&&typeof m=="string"&&ya.test(m)&&delete p.scripts[d];p.scripts.lint=ba(p.scripts.lint,o),Tt.writeFileSync(a,JSON.stringify(p,null,2)+`
1517
+ `)}return{lints:o,configWritten:!0}}import Z from"fs";import ce from"path";import{fileURLToPath as Pa}from"url";var wa=Pa(import.meta.url),Xo=ce.dirname(wa),zo="scaffold-meta.json",Jo=".nebutra";function Aa(e){if(e)return e;let t=[ce.join(Xo,"..","templates"),ce.join(Xo,"..","..","templates")];for(let n of t)if(Z.existsSync(n))return n;return t[0]}function Qo(e,t){let n=[],o=Aa(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,Jo);Z.mkdirSync(a,{recursive:!0}),Z.writeFileSync(ce.join(a,zo),`${JSON.stringify(i,null,2)}
1518
+ `),n.push(`${Jo}/${zo}`);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 De from"fs";import dn from"path";async function Go(e,t){let n=dn.join(e,"packages","mcp");if(t==="off"){De.existsSync(n)&&De.rmSync(n,{recursive:!0,force:!0});let r=dn.join(e,"packages","cli","src","commands","mcp-server.ts");De.existsSync(r)&&De.rmSync(r,{force:!0});return}let o=dn.join(e,".env.example");if(De.existsSync(o)){let r=De.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
- `);De.appendFileSync(o,i)}}}import lt from"fs";import Ho from"path";async function Wo(e,t,n){let o=Ho.join(e,"packages","metering"),r;if(t==="auto"?r=n!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){lt.existsSync(o)&&lt.rmSync(o,{recursive:!0,force:!0});return}let s=Ho.join(e,".env.example");if(!lt.existsSync(s))return;let i=lt.readFileSync(s,"utf-8"),a="# Metering (usage-based billing)";if(!i.includes(a)){let c=["","# =============================================",a,"# Docs: see packages/commerce/metering/README.md","# =============================================","# ClickHouse-based metering pipeline for consumption billing.",'CLICKHOUSE_URL=""','CLICKHOUSE_USER="default"','CLICKHOUSE_PASSWORD=""','CLICKHOUSE_DATABASE="metering"',""].join(`
1525
- `);lt.appendFileSync(s,c)}}import ue from"fs";import M from"path";var Xo=[{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:""}],yd=Xo.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function zo(e){return Xo.find(t=>t.id===e)}var un={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 ya(e){ue.mkdirSync(e,{recursive:!0})}function mn(e,t){let n=M.join(e,"package.json");if(!ue.existsSync(n))return;let o;try{o=JSON.parse(ue.readFileSync(n,"utf-8"))}catch(a){console.error(`Failed to parse ${n}:`,a);return}let s={...o.dependencies??{}};for(let[a,c]of Object.entries(t))s[a]||(s[a]=c);let i={...o,dependencies:s};ue.writeFileSync(n,JSON.stringify(i,null,2)+`
1526
- `)}function ce(e,t){ya(M.dirname(e)),ue.writeFileSync(e,t)}function dt(e,t){let n=M.join(e,".env.example");ue.existsSync(n)?ue.appendFileSync(n,`
1527
- `+t):ue.writeFileSync(n,t)}function Sa(e){let t=`import * as Sentry from "@sentry/nextjs";
1523
+ `+p),n.push("README.md (prepended license notice)"))}return{wrote:n}}import Be from"fs";import fn from"path";async function Zo(e,t){let n=fn.join(e,"packages","mcp");if(t==="off"){Be.existsSync(n)&&Be.rmSync(n,{recursive:!0,force:!0});let r=fn.join(e,"packages","cli","src","commands","mcp-server.ts");Be.existsSync(r)&&Be.rmSync(r,{force:!0});return}let o=fn.join(e,".env.example");if(Be.existsSync(o)){let r=Be.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
+ `);Be.appendFileSync(o,i)}}}import gt from"fs";import er from"path";async function tr(e,t,n){let o=er.join(e,"packages","metering"),r;if(t==="auto"?r=n!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){gt.existsSync(o)&&gt.rmSync(o,{recursive:!0,force:!0});return}let s=er.join(e,".env.example");if(!gt.existsSync(s))return;let i=gt.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
+ `);gt.appendFileSync(s,c)}}import me from"fs";import j from"path";var nr=[{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:""}],xd=nr.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function or(e){return nr.find(t=>t.id===e)}var yn={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 Ca(e){me.mkdirSync(e,{recursive:!0})}function Sn(e,t){let n=j.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){Ca(j.dirname(e)),me.writeFileSync(e,t)}function ft(e,t){let n=j.join(e,".env.example");me.existsSync(n)?me.appendFileSync(n,`
1527
+ `+t):me.writeFileSync(n,t)}function Ia(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
- `;ce(M.join(e,"sentry.client.config.ts"),t),ce(M.join(e,"sentry.server.config.ts"),n),ce(M.join(e,"sentry.edge.config.ts"),o),ce(M.join(e,"instrumentation.ts"),r)}function ha(){return`# Sentry \u2014 error tracking + performance monitoring
1570
+ `;pe(j.join(e,"sentry.client.config.ts"),t),pe(j.join(e,"sentry.server.config.ts"),n),pe(j.join(e,"sentry.edge.config.ts"),o),pe(j.join(e,"instrumentation.ts"),r)}function xa(){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 Ea(e){let t=`/**
1577
+ `}function Ra(e){let t=`/**
1578
1578
  * Next.js instrumentation hook \u2014 wires Datadog APM (dd-trace) into Node runtime.
1579
1579
  * Edge runtime is not supported by dd-trace; only nodejs is initialized.
1580
1580
  */
@@ -1622,7 +1622,7 @@ export function initDatadogRum(): void {
1622
1622
  });
1623
1623
  initialized = true;
1624
1624
  }
1625
- `;ce(M.join(e,"instrumentation.ts"),t),ce(M.join(e,"src","lib","monitoring","datadog-rum.ts"),n)}function va(){return`# Datadog \u2014 APM + RUM
1625
+ `;pe(j.join(e,"instrumentation.ts"),t),pe(j.join(e,"src","lib","monitoring","datadog-rum.ts"),n)}function Ta(){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 ba(e){let t=`/**
1640
+ `}function ka(e){let t=`/**
1641
1641
  * Bugsnag server-side initialization.
1642
1642
  * Import this once at the top of your server entrypoint or a shared init module.
1643
1643
  */
@@ -1686,11 +1686,11 @@ export function getBugsnagErrorBoundary() {
1686
1686
  errorBoundary = plugin.createErrorBoundary(React) as typeof errorBoundary;
1687
1687
  return errorBoundary;
1688
1688
  }
1689
- `;ce(M.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),ce(M.join(e,"src","lib","monitoring","bugsnag.client.tsx"),n)}function _a(){return`# Bugsnag \u2014 error tracking
1689
+ `;pe(j.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),pe(j.join(e,"src","lib","monitoring","bugsnag.client.tsx"),n)}function Na(){return`# Bugsnag \u2014 error tracking
1690
1690
  BUGSNAG_API_KEY=
1691
1691
  NEXT_PUBLIC_BUGSNAG_API_KEY=
1692
1692
  APP_VERSION=
1693
- `}function Pa(e){ce(M.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1693
+ `}function Oa(e){pe(j.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 wa(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1714
+ `)}function La(){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 Aa(e){ce(M.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1718
+ `}function Ua(e){pe(j.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 Ia(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1736
+ `)}function Da(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1737
1737
  TINGYUN_LICENSE_KEY=
1738
1738
  NEXT_PUBLIC_TINGYUN_APP_KEY=
1739
- `}async function Jo(e,t,n="global"){let o=zo(t);if(!o||o.id==="none")return;let r=M.join(e,"apps","web");if(!ue.existsSync(r))return;let s=o.id;try{switch(s){case"sentry":Sa(r),mn(r,un.sentry),dt(e,ha());return;case"datadog":Ea(r),mn(r,un.datadog),dt(e,va());return;case"bugsnag":ba(r),mn(r,un.bugsnag),dt(e,_a());return;case"aliyun-arms":Pa(r),dt(e,wa());return;case"tingyun":Aa(r),dt(e,Ia());return;default:return}}catch(i){throw console.error(`Failed to apply monitoring selection "${t}":`,i),new Error(`Monitoring scaffold for "${t}" failed \u2014 see stderr for details.`)}}var Ct=[{id:"novu",name:"Novu",region:"both",envVars:["NOVU_API_KEY","NOVU_APPLICATION_IDENTIFIER"],docs:"https://docs.novu.co",description:"Multi-channel notification infrastructure"},{id:"knock",name:"Knock",region:"global",envVars:["KNOCK_API_KEY","KNOCK_SIGNING_KEY","KNOCK_PUBLIC_API_KEY"],docs:"https://docs.knock.app",description:"Product notifications platform"},{id:"custom",name:"Custom (direct dispatchers)",region:"both",envVars:[],docs:"",description:"Use email + sms + push directly"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Qo(e){return Ct.find(t=>t.id===e)}var _d=Ct.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Zo(e,t,n="global"){let o=Qo(t);if(!o)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${Ct.map(r=>r.id).join(", ")}`);if(o.id==="none"){z(e,"notifications");return}o.envVars.length>0&&oe(e,{category:"Notifications",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"NOTIFICATIONS_PROVIDER",o.id)}import gn from"fs";import Ca from"path";async function er(e,t){let n=Ca.join(e,"package.json");if(gn.existsSync(n)){let o=gn.readFileSync(n,"utf8"),r=JSON.parse(o);r.name=t,r.version="0.1.0",gn.writeFileSync(n,JSON.stringify(r,null,2)+`
1740
- `)}}import xt from"fs";import Qe from"path";import{fileURLToPath as xa}from"url";var Ra=xa(import.meta.url),tr=Qe.dirname(Ra);function Ta(){let e=[Qe.join(tr,"..","templates","orm","drizzle"),Qe.join(tr,"..","..","templates","orm","drizzle")];for(let t of e)if(xt.existsSync(t))return t;return null}function nr(e,t){xt.mkdirSync(t,{recursive:!0});for(let n of xt.readdirSync(e,{withFileTypes:!0})){let o=Qe.join(e,n.name),r=Qe.join(t,n.name);n.isDirectory()?nr(o,r):xt.copyFileSync(o,r)}}async function or(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=Ta();if(!o)return{applied:!1,reason:"Drizzle template directory not found in package \u2014 bundling error"};let r=Qe.join(e,"packages","platform","db-drizzle");return nr(o,r),{applied:!0}}import me from"fs";import ut from"path";var ka=["stripe","lemonsqueezy","chinapay","polar"];function rr(e){me.existsSync(e)&&me.rmSync(e,{recursive:!0,force:!0})}function Na(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function Oa(e,t){let n=ut.join(e,".env.example");me.existsSync(n)?me.appendFileSync(n,`
1741
- `+t):me.writeFileSync(n,t)}function La(e){switch(e){case"stripe":return`# Stripe
1739
+ `}async function rr(e,t,n="global"){let o=or(t);if(!o||o.id==="none")return;let r=j.join(e,"apps","web");if(!me.existsSync(r))return;let s=o.id;try{switch(s){case"sentry":Ia(r),Sn(r,yn.sentry),ft(e,xa());return;case"datadog":Ra(r),Sn(r,yn.datadog),ft(e,Ta());return;case"bugsnag":ka(r),Sn(r,yn.bugsnag),ft(e,Na());return;case"aliyun-arms":Oa(r),ft(e,La());return;case"tingyun":Ua(r),ft(e,Da());return;default:return}}catch(i){throw console.error(`Failed to apply monitoring selection "${t}":`,i),new Error(`Monitoring scaffold for "${t}" failed \u2014 see stderr for details.`)}}var kt=[{id:"novu",name:"Novu",region:"both",envVars:["NOVU_API_KEY","NOVU_APPLICATION_IDENTIFIER"],docs:"https://docs.novu.co",description:"Multi-channel notification infrastructure"},{id:"knock",name:"Knock",region:"global",envVars:["KNOCK_API_KEY","KNOCK_SIGNING_KEY","KNOCK_PUBLIC_API_KEY"],docs:"https://docs.knock.app",description:"Product notifications platform"},{id:"custom",name:"Custom (direct dispatchers)",region:"both",envVars:[],docs:"",description:"Use email + sms + push directly"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function sr(e){return kt.find(t=>t.id===e)}var Ld=kt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function ir(e,t,n="global"){let o=sr(t);if(!o)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${kt.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 hn from"fs";import Ma from"path";async function ar(e,t){let n=Ma.join(e,"package.json");if(hn.existsSync(n)){let o=hn.readFileSync(n,"utf8"),r=JSON.parse(o);r.name=t,r.version="0.1.0",hn.writeFileSync(n,JSON.stringify(r,null,2)+`
1740
+ `)}}import Nt from"fs";import tt from"path";import{fileURLToPath as Fa}from"url";var ja=Fa(import.meta.url),cr=tt.dirname(ja);function Ba(){let e=[tt.join(cr,"..","templates","orm","drizzle"),tt.join(cr,"..","..","templates","orm","drizzle")];for(let t of e)if(Nt.existsSync(t))return t;return null}function pr(e,t){Nt.mkdirSync(t,{recursive:!0});for(let n of Nt.readdirSync(e,{withFileTypes:!0})){let o=tt.join(e,n.name),r=tt.join(t,n.name);n.isDirectory()?pr(o,r):Nt.copyFileSync(o,r)}}async function lr(e,t,n){if(t!=="drizzle")return{applied:!1};if(n!=="postgresql")return{applied:!1,reason:`Drizzle template currently targets Postgres only; --db=${n} keeps Prisma as sole ORM`};let o=Ba();if(!o)return{applied:!1,reason:"Drizzle template directory not found in package \u2014 bundling error"};let r=tt.join(e,"packages","platform","db-drizzle");return pr(o,r),{applied:!0}}import ge from"fs";import yt from"path";var $a=["stripe","lemonsqueezy","chinapay","polar"];function dr(e){ge.existsSync(e)&&ge.rmSync(e,{recursive:!0,force:!0})}function Va(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function Ka(e,t){let n=yt.join(e,".env.example");ge.existsSync(n)?ge.appendFileSync(n,`
1741
+ `+t):ge.writeFileSync(n,t)}function Ya(e){switch(e){case"stripe":return`# Stripe
1742
1742
  STRIPE_SECRET_KEY=
1743
1743
  STRIPE_WEBHOOK_SECRET=
1744
1744
  `;case"lemon":return`# Lemon Squeezy
@@ -1753,14 +1753,14 @@ CHINAPAY_WECHAT_ENABLED=true
1753
1753
  CHINAPAY_APP_ID=
1754
1754
  CHINAPAY_APP_SECRET=
1755
1755
  CHINAPAY_ALIPAY_ENABLED=true
1756
- `}}async function sr(e,t){let n=ut.join(e,"packages","commerce","billing");if(!me.existsSync(n))return;if(t==="none"){rr(n);return}let o=ut.join(n,"src"),r=new Set(Na(t));for(let i of ka)r.has(i)||rr(ut.join(o,i));let s=ut.join(o,"checkout","types.ts");if(me.existsSync(s)){let i=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",a=me.readFileSync(s,"utf8"),c=a.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${i}";`);c!==a&&me.writeFileSync(s,c)}Oa(e,La(t))}import _e from"fs";import Ze from"path";var cr=new Set(["siliconflow","volcengine-ark","bailian","moonshot","sensetime"]),fn=/@sailor:([^\s*]+)/;function Ua(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=>cr.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 ir(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function ar(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function pr(e,t){let n=e.split(`
1757
- `),o=[],r=e.includes("#"),s=0;for(;s<n.length;){let i=n[s],a=i.match(fn);if(!a){o.push(i),s++;continue}let{marker:c,keep:p}=Ua(a[1],t);if(c==="registry-entries"){o.push(r?ar(i):ir(i)),s++;continue}if(p){let u=r?ar(i):ir(i);u.trim().length>0&&o.push(u);let d=s+1;for(;d<n.length&&n[d].trim()!==""&&!fn.test(n[d]);)o.push(n[d]),d++;d<n.length&&n[d].trim()===""&&(o.push(n[d]),d++),s=d}else{let u=s+1;for(;u<n.length&&n[u].trim()!==""&&!fn.test(n[u]);)u++;u<n.length&&n[u].trim()===""&&u++,s=u}}return Da(o.join(`
1758
- `),t)}function Da(e,t){let{providerIds:n,customEndpoint:o}=t,r=new Set;for(let p of n)["openai","anthropic","google","mistral","xai"].includes(p)&&r.add(p),r.add(p.replace(/-/g,"_")),r.add(p);o&&r.add("custom");let s=/createProviderRegistry\(\{([\s\S]*?)\}\)/,i=e.match(s);if(!i)return e;let c=i[1].split(`
1759
- `).filter(p=>{let u=p.trim();if(u===""||u.startsWith("//"))return!0;let d=u.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return d?r.has(d[1]):!0}).join(`
1760
- `);return e.replace(s,`createProviderRegistry({${c}})`)}function Ma(e,t){let n=Ze.join(t,"registry.ts.template"),o=_e.readFileSync(n,"utf-8");return pr(o,e)}function Fa(e,t){let n=Ze.join(t,".env.example.template"),o=_e.readFileSync(n,"utf-8");return pr(o,e)}async function lr(e,t,n){let o=Ma(t,n),r=Fa(t,n),s=Ze.join(e,"packages/ai/agents/src");await _e.promises.mkdir(s,{recursive:!0}),await _e.promises.writeFile(Ze.join(s,"registry.ts"),o),await _e.promises.appendFile(Ze.join(e,".env.example"),`
1761
- `+r);let i={ai:"latest"},{providerIds:a,customEndpoint:c}=t;(a.includes("openai")||c||a.some(u=>cr.has(u)))&&(i["@ai-sdk/openai"]="latest",i["@ai-sdk/openai-compatible"]="latest"),a.includes("anthropic")&&(i["@ai-sdk/anthropic"]="latest"),a.includes("google")&&(i["@ai-sdk/google"]="latest"),a.includes("mistral")&&(i["@ai-sdk/mistral"]="latest"),a.includes("xai")&&(i["@ai-sdk/openai"]="latest");let p=Ze.join(e,"package.json");if(_e.existsSync(p)){let u=JSON.parse(await _e.promises.readFile(p,"utf-8"));u.dependencies||(u.dependencies={});for(let[d,A]of Object.entries(i))u.dependencies[d]=A;await _e.promises.writeFile(p,JSON.stringify(u,null,2)+`
1762
- `)}}import y from"fs";import g from"path";function dr(e,t){if(!y.existsSync(e))return;let n=y.readdirSync(e);for(let o of n){let r=g.join(e,o);y.statSync(r).isDirectory()?dr(r,t):t(r)}}async function ur(e,t){let n=g.join(e,"package.json");if(!y.existsSync(n))return;let o=JSON.parse(y.readFileSync(n,"utf8"));if(t.orm!=="prisma"){let r=g.join(e,"packages","db");if(y.existsSync(r)){let s=g.join(r,"prisma");y.existsSync(s)&&y.rmSync(s,{recursive:!0,force:!0});let i=g.join(r,"package.json");if(y.existsSync(i)){let c=JSON.parse(y.readFileSync(i,"utf8"));c.dependencies&&delete c.dependencies["@prisma/client"],c.devDependencies&&delete c.devDependencies.prisma,y.writeFileSync(i,JSON.stringify(c,null,2)+`
1763
- `)}let a=g.join(r,"src","index.ts");y.existsSync(a)&&y.writeFileSync(a,`
1756
+ `}}async function ur(e,t){let n=yt.join(e,"packages","commerce","billing");if(!ge.existsSync(n))return;if(t==="none"){dr(n);return}let o=yt.join(n,"src"),r=new Set(Va(t));for(let i of $a)r.has(i)||dr(yt.join(o,i));let s=yt.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)}Ka(e,Ya(t))}import Ae from"fs";import nt from"path";var fr=new Set(["siliconflow","volcengine-ark","bailian","moonshot","sensetime"]),En=/@sailor:([^\s*]+)/;function qa(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=>fr.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 mr(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function gr(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function yr(e,t){let n=e.split(`
1757
+ `),o=[],r=e.includes("#"),s=0;for(;s<n.length;){let i=n[s],a=i.match(En);if(!a){o.push(i),s++;continue}let{marker:c,keep:p}=qa(a[1],t);if(c==="registry-entries"){o.push(r?gr(i):mr(i)),s++;continue}if(p){let d=r?gr(i):mr(i);d.trim().length>0&&o.push(d);let m=s+1;for(;m<n.length&&n[m].trim()!==""&&!En.test(n[m]);)o.push(n[m]),m++;m<n.length&&n[m].trim()===""&&(o.push(n[m]),m++),s=m}else{let d=s+1;for(;d<n.length&&n[d].trim()!==""&&!En.test(n[d]);)d++;d<n.length&&n[d].trim()===""&&d++,s=d}}return Ga(o.join(`
1758
+ `),t)}function Ga(e,t){let{providerIds:n,customEndpoint:o}=t,r=new Set;for(let p of n)["openai","anthropic","google","mistral","xai"].includes(p)&&r.add(p),r.add(p.replace(/-/g,"_")),r.add(p);o&&r.add("custom");let s=/createProviderRegistry\(\{([\s\S]*?)\}\)/,i=e.match(s);if(!i)return e;let c=i[1].split(`
1759
+ `).filter(p=>{let d=p.trim();if(d===""||d.startsWith("//"))return!0;let m=d.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return m?r.has(m[1]):!0}).join(`
1760
+ `);return e.replace(s,`createProviderRegistry({${c}})`)}function Ha(e,t){let n=nt.join(t,"registry.ts.template"),o=Ae.readFileSync(n,"utf-8");return yr(o,e)}function Wa(e,t){let n=nt.join(t,".env.example.template"),o=Ae.readFileSync(n,"utf-8");return yr(o,e)}async function Sr(e,t,n){let o=Ha(t,n),r=Wa(t,n),s=nt.join(e,"packages/ai/agents/src");await Ae.promises.mkdir(s,{recursive:!0}),await Ae.promises.writeFile(nt.join(s,"registry.ts"),o),await Ae.promises.appendFile(nt.join(e,".env.example"),`
1761
+ `+r);let i={ai:"latest"},{providerIds:a,customEndpoint:c}=t;(a.includes("openai")||c||a.some(d=>fr.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=nt.join(e,"package.json");if(Ae.existsSync(p)){let d=JSON.parse(await Ae.promises.readFile(p,"utf-8"));d.dependencies||(d.dependencies={});for(let[m,C]of Object.entries(i))d.dependencies[m]=C;await Ae.promises.writeFile(p,JSON.stringify(d,null,2)+`
1762
+ `)}}import y from"fs";import f from"path";function hr(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()?hr(r,t):t(r)}}async function Er(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
+ `)}let a=f.join(r,"src","index.ts");y.existsSync(a)&&y.writeFileSync(a,`
1764
1764
  export const prisma = {} as any;
1765
1765
  export const db = {} as any;
1766
1766
  export type PrismaClient = any;
@@ -1806,7 +1806,7 @@ export type UsageAggregate = any;
1806
1806
  export type UsageLedgerEntry = any;
1807
1807
  export type UsageType = any;
1808
1808
  export type UsageLedgerSource = any;
1809
- `)}o.scripts?.postinstall&&(o.scripts.postinstall=o.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let r=g.join(e,"apps");if(y.existsSync(r)){let s=y.readdirSync(r);for(let i of s){let a=g.join(r,i);if(!y.statSync(a).isDirectory())continue;let c=g.join(a,"src","app");if(!y.existsSync(c))continue;["[lang]","[locale]"].forEach(S=>{let m=g.join(c,S);if(y.existsSync(m)){let _=y.readdirSync(m);for(let G of _)y.renameSync(g.join(m,G),g.join(c,G));y.rmdirSync(m)}}),["src/middleware.ts","middleware.ts"].forEach(S=>{let m=g.join(a,S);y.existsSync(m)&&y.rmSync(m)});let p=g.join(a,"src","lib");y.existsSync(p)||y.mkdirSync(p,{recursive:!0});let u=g.join(p,"mock-i18n.ts");y.writeFileSync(u,`
1809
+ `)}o.scripts?.postinstall&&(o.scripts.postinstall=o.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let r=f.join(e,"apps");if(y.existsSync(r)){let s=y.readdirSync(r);for(let i of s){let a=f.join(r,i);if(!y.statSync(a).isDirectory())continue;let c=f.join(a,"src","app");if(!y.existsSync(c))continue;["[lang]","[locale]"].forEach(S=>{let u=f.join(c,S);if(y.existsSync(u)){let _=y.readdirSync(u);for(let H of _)y.renameSync(f.join(u,H),f.join(c,H));y.rmdirSync(u)}}),["src/middleware.ts","middleware.ts"].forEach(S=>{let u=f.join(a,S);y.existsSync(u)&&y.rmSync(u)});let p=f.join(a,"src","lib");y.existsSync(p)||y.mkdirSync(p,{recursive:!0});let d=f.join(p,"mock-i18n.ts");y.writeFileSync(d,`
1810
1810
  import React from 'react';
1811
1811
  export function useTranslations(namespace?: string): any { return (key: string) => key; }
1812
1812
  export function useLocale() { return 'en'; }
@@ -1824,7 +1824,7 @@ export const useRouter = () => ({ push: (...args: any[]) => {}, replace: (...arg
1824
1824
  export default function createMiddleware(...args: any[]) { return (req: any) => req; }
1825
1825
  export function createNavigation(...args: any[]) { return { Link, redirect, usePathname, useRouter, getPathname: () => '/' }; }
1826
1826
  export function defineRouting<T>(config: T): T { return config; }
1827
- `);let A=g.join(p,"mock-i18n.d.ts");y.writeFileSync(A,`declare module '@/lib/mock-i18n' {
1827
+ `);let C=f.join(p,"mock-i18n.d.ts");y.writeFileSync(C,`declare module '@/lib/mock-i18n' {
1828
1828
  export function useTranslations(namespace?: string): any;
1829
1829
  export function useLocale(): string;
1830
1830
  export const NextIntlClientProvider: React.FC<any>;
@@ -1842,19 +1842,19 @@ export function defineRouting<T>(config: T): T { return config; }
1842
1842
  export function createNavigation(...args: any[]): any;
1843
1843
  export function defineRouting<T>(config: T): T;
1844
1844
  }
1845
- `),y.writeFileSync(g.join(p,"mock-i18n-index.ts"),`
1845
+ `),y.writeFileSync(f.join(p,"mock-i18n-index.ts"),`
1846
1846
  export * from './mock-i18n';
1847
1847
  export { default } from './mock-i18n';
1848
- `);let b=g.join(a,"tsconfig.json");if(y.existsSync(b))try{let S=y.readFileSync(b,"utf8");if(S.includes('"paths": {')){let m=S.replace(/"paths":\s*\{/,`"paths": {
1848
+ `);let E=f.join(a,"tsconfig.json");if(y.existsSync(E))try{let S=y.readFileSync(E,"utf8");if(S.includes('"paths": {')){let u=S.replace(/"paths":\s*\{/,`"paths": {
1849
1849
  "next-intl": ["./src/lib/mock-i18n"],
1850
- "next-intl/*": ["./src/lib/mock-i18n"],`);y.writeFileSync(b,m)}}catch{}let f=g.join(a,"src");y.existsSync(f)&&dr(f,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 h=g.join(a,"package.json");if(y.existsSync(h)){let S=JSON.parse(y.readFileSync(h,"utf8"));S.dependencies&&delete S.dependencies["next-intl"],y.writeFileSync(h,JSON.stringify(S,null,2)+`
1850
+ "next-intl/*": ["./src/lib/mock-i18n"],`);y.writeFileSync(E,u)}}catch{}let g=f.join(a,"src");y.existsSync(g)&&hr(g,S=>{if(!S.endsWith(".ts")&&!S.endsWith(".tsx"))return;let u=y.readFileSync(S,"utf8"),_=!1;S.endsWith("src/app/layout.tsx")&&u.includes("../providers")&&(u=u.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),_=!0),u=u.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),u=u.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),u.match(/locale\s*:\s*any/)&&(u=u.replace(/locale\s*:\s*any/g,"locale: string"),_=!0),u.match(/lang\s*:\s*any/)&&(u=u.replace(/lang\s*:\s*any/g,"lang: string"),_=!0),u.match(/requestLocale\s*:\s*any/)&&(u=u.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),_=!0),u.match(/\(locale\s*=\s*(.*)\)/)&&(u=u.replace(/\(locale\s*=\s*(.*)\)/g,"() "),_=!0),u.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(u=u.replace(/export\s+default\s+async\s+function\s+LangLayout\s*\(\s*\{\s*children\s*,\s*params\s*\}\s*:\s*LangLayoutProps\s*\)/g,"export default async function LangLayout({ children }: { children: React.ReactNode })"),_=!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"))&&(u=u.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),u=u.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),u=u.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),u=u.replace(/\(l\)\s*=>/g,"(l: any) =>"),_=!0),S.endsWith("src/i18n/request.ts")&&(u=u.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),_=!0),(u.match(/locale\s*:/)||u.match(/lang\s*:/))&&(_=!0),_&&y.writeFileSync(S,u)});let h=f.join(a,"package.json");if(y.existsSync(h)){let S=JSON.parse(y.readFileSync(h,"utf8"));S.dependencies&&delete S.dependencies["next-intl"],y.writeFileSync(h,JSON.stringify(S,null,2)+`
1851
1851
  `)}}}}y.writeFileSync(n,JSON.stringify(o,null,2)+`
1852
- `)}function v(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 mr(e,t){t.cronJobs||(v(g.join(e,"apps/web/src/app/api/cron")),v(g.join(e,"packages/integrations/queue/src/scheduled"))),t.auditLog||(v(g.join(e,"apps/web/src/app/[locale]/(app)/settings/audit-log")),v(g.join(e,"apps/web/src/app/api/audit-logs")),v(g.join(e,"apps/web/src/components/audit"))),t.apiKeys||(v(g.join(e,"apps/web/src/app/[locale]/(app)/settings/api-keys")),v(g.join(e,"apps/web/src/app/api/api-keys")),v(g.join(e,"apps/web/src/components/api-keys"))),t.webhooks||(v(g.join(e,"apps/web/src/app/[locale]/(app)/settings/webhooks")),v(g.join(e,"apps/web/src/app/api/webhooks")),v(g.join(e,"apps/web/src/components/webhooks")),v(g.join(e,"packages/integrations/webhooks"))),t.commandPalette||(v(g.join(e,"apps/web/src/components/command-palette")),v(g.join(e,"apps/web/src/app/[locale]/providers/command-palette-mount.tsx"))),t.cookieConsent||(v(g.join(e,"apps/landing/src/components/cookie-consent-banner.tsx")),v(g.join(e,"apps/landing/src/components/__tests__/cookie-consent-banner.test.tsx")),v(g.join(e,"apps/landing/src/lib/cookie-consent.ts")),v(g.join(e,"apps/landing/src/lib/__tests__/cookie-consent.test.ts")),v(g.join(e,"apps/web/src/app/api/cookie-consent"))),t.legalPages||(v(g.join(e,"apps/landing/src/app/[lang]/(legal)/legal")),v(g.join(e,"apps/landing/src/lib/legal-documents.ts")),v(g.join(e,"apps/landing/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(v(g.join(e,"packages/ops/china-compliance")),v(g.join(e,"apps/landing/src/components/icp-footer.tsx")),v(g.join(e,"apps/landing/src/components/__tests__/icp-footer.test.tsx")),v(g.join(e,"apps/web/src/components/auth/wechat-login-button.tsx")),v(g.join(e,"apps/web/src/components/auth/__tests__/wechat-login-button.test.tsx")),ja(g.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import et from"fs";import gr from"path";var fr=/^--\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/m;function Ba(e){let t=fr.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 Va(e){return e.replace(fr,"").replace(/^\n/,"")}function yn(e,t){let n={kept:[],removed:[],skipped:[]};if(!et.existsSync(e))return n;let o=et.readdirSync(e,{withFileTypes:!0}).filter(r=>r.isDirectory()).sort((r,s)=>r.name.localeCompare(s.name));for(let r of o){let s=gr.join(e,r.name),i=gr.join(s,"migration.sql");if(!et.existsSync(i)){n.skipped.push(r.name);continue}let a=et.readFileSync(i,"utf8"),c=Ba(a);if(!c){n.skipped.push(r.name);continue}let p=t[c.flag];if(p!==void 0&&c.values.includes(p)){et.writeFileSync(i,Va(a)),n.kept.push(r.name);continue}et.rmSync(s,{recursive:!0,force:!0}),n.removed.push(r.name)}return n}import{getSchema as $a,printSchema as Ka}from"@mrleebo/prisma-ast";var Ya=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function qa(e){return e.type==="comment"&&e.text.trim().startsWith("//")}function Ga(e){let t=Ya.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 Ha(e,t){for(let n=t-1;n>=0;n--){let o=e[n];if(o.type==="comment"){let r=Ga(o.text);if(r)return{annIndex:n,parsed:r};continue}break}return null}function Wa(e){return e.type==="model"||e.type==="enum"}function Sn(e,t){let n=$a(e),o=new Set;for(let a=0;a<n.list.length;a++){let c=n.list[a];if(!Wa(c))continue;let p=Ha(n.list,a);if(!p)continue;let u=t[p.parsed.flag];if(u!==void 0&&p.parsed.values.includes(u))o.add(p.annIndex);else{o.add(a);for(let b=a-1;b>=0;b--){let f=n.list[b];if(qa(f)){o.add(b);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 Ka({type:"schema",list:s})}import tt from"fs";import Sr from"path";var Rt=[{id:"qstash",name:"Upstash QStash",region:"both",envVars:["QSTASH_TOKEN","QSTASH_CURRENT_SIGNING_KEY","QSTASH_NEXT_SIGNING_KEY"],docs:"https://upstash.com/docs/qstash",description:"Serverless HTTP-based queue"},{id:"bullmq",name:"BullMQ",region:"both",envVars:["REDIS_URL"],docs:"https://docs.bullmq.io",description:"Redis-backed job queue"},{id:"sqs",name:"AWS SQS",region:"global",envVars:["AWS_SQS_QUEUE_URL","AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_REGION"],docs:"https://docs.aws.amazon.com/AWSSimpleQueueService/",description:"AWS managed queue"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip queue package"}];function yr(e){return Rt.find(t=>t.id===e)}var Wd=Rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function hr(e){return tt.existsSync(e)?tt.readFileSync(e,"utf-8"):null}function Xa(e,t){let n=Sr.join(e,".env.example"),o=hr(n);if(o===null)return;let r=`# Queue: ${t.name}`;if(o.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1854
- `);tt.appendFileSync(n,s)}function za(e,t,n){let o=Sr.join(e,".env.example"),r=hr(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?tt.writeFileSync(o,r.replace(s,`${t}="${n}"`)):tt.appendFileSync(o,`${t}="${n}"
1855
- `)}async function Er(e,t,n){let o=Re(e,"queue");if(t==="none"){o&&tt.rmSync(o,{recursive:!0,force:!0});return}let r=yr(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${Rt.map(s=>s.id).join(", ")}`);o&&(Xa(e,r),za(e,"QUEUE_PROVIDER",t))}import ge from"fs";import Pe from"path";import{fileURLToPath as Ja}from"url";var Qa=Ja(import.meta.url),vr=Pe.dirname(Qa),Za=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|toml|py)$/,ec=["backends/gateway","infra","e2e","tests"];function tc(){let e=[Pe.join(vr,"..","templates"),Pe.join(vr,"..","..","templates")];for(let t of e)if(ge.existsSync(t))return t;return e[0]}async function br(e,t){let n=tc(),o=[],r=[],s=[...ec,...t.withWorkflows?["workflows"]:[],...t.withPythonBackend?["backends/python"]:[]];for(let i of s){let a=Pe.join(n,i);if(!ge.existsSync(a)){r.push(i);continue}let c=Pe.join(e,i);_r(a,c),Pr(c,{"{PRODUCT_NAME}":t.projectName}),o.push(i)}return{applied:o,skipped:r}}function _r(e,t){ge.mkdirSync(t,{recursive:!0});for(let n of ge.readdirSync(e,{withFileTypes:!0})){let o=Pe.join(e,n.name),r=Pe.join(t,n.name);n.isDirectory()?_r(o,r):ge.existsSync(r)||ge.copyFileSync(o,r)}}function Pr(e,t){for(let n of ge.readdirSync(e,{withFileTypes:!0})){let o=Pe.join(e,n.name);if(n.isDirectory()){Pr(o,t);continue}if(!Za.test(n.name))continue;let r=ge.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&&ge.writeFileSync(o,r)}}import nt from"fs";import Ar from"path";var Tt=[{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 wr(e){return Tt.find(t=>t.id===e)}var su=Tt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ir(e){return nt.existsSync(e)?nt.readFileSync(e,"utf-8"):null}function nc(e,t){let n=Ar.join(e,".env.example"),o=Ir(n);if(o===null)return;let r=`# Search: ${t.name}`;if(o.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1856
- `);nt.appendFileSync(n,s)}function oc(e,t,n){let o=Ar.join(e,".env.example"),r=Ir(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?nt.writeFileSync(o,r.replace(s,`${t}="${n}"`)):nt.appendFileSync(o,`${t}="${n}"
1857
- `)}async function Cr(e,t,n){let o=Re(e,"search");if(t==="none"){o&&nt.rmSync(o,{recursive:!0,force:!0});return}let r=wr(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${Tt.map(s=>s.id).join(", ")}`);o&&(nc(e,r),oc(e,"SEARCH_PROVIDER",t))}import we from"fs";import Me from"path";function rc(e){let t=[Me.join(e,"packages","db"),Me.join(e,"apps","web")];for(let n of t){let o=Me.join(n,"prisma","schema.prisma");if(we.existsSync(o))return{packageDir:n,seedPath:Me.join(n,"prisma","seed.ts"),packageJsonPath:Me.join(n,"package.json")}}return null}function sc(e){try{let t=we.readFileSync(e,"utf8"),n=new Set,o=/^\s*model\s+(\w+)\s*\{/gm,r=o.exec(t);for(;r;)n.add(r[1]),r=o.exec(t);return n}catch{return new Set}}function ic(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 Xa(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 vr(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")),Xa(f.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import ot from"fs";import br from"path";var _r=/^--\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/m;function za(e){let t=_r.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 Ja(e){return e.replace(_r,"").replace(/^\n/,"")}function vn(e,t){let n={kept:[],removed:[],skipped:[]};if(!ot.existsSync(e))return n;let o=ot.readdirSync(e,{withFileTypes:!0}).filter(r=>r.isDirectory()).sort((r,s)=>r.name.localeCompare(s.name));for(let r of o){let s=br.join(e,r.name),i=br.join(s,"migration.sql");if(!ot.existsSync(i)){n.skipped.push(r.name);continue}let a=ot.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)){ot.writeFileSync(i,Ja(a)),n.kept.push(r.name);continue}ot.rmSync(s,{recursive:!0,force:!0}),n.removed.push(r.name)}return n}import{getSchema as Qa,printSchema as Za}from"@mrleebo/prisma-ast";var ec=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function tc(e){return e.type==="comment"&&e.text.trim().startsWith("//")}function nc(e){let t=ec.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 oc(e,t){for(let n=t-1;n>=0;n--){let o=e[n];if(o.type==="comment"){let r=nc(o.text);if(r)return{annIndex:n,parsed:r};continue}break}return null}function rc(e){return e.type==="model"||e.type==="enum"}function bn(e,t){let n=Qa(e),o=new Set;for(let a=0;a<n.list.length;a++){let c=n.list[a];if(!rc(c))continue;let p=oc(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 E=a-1;E>=0;E--){let g=n.list[E];if(tc(g)){o.add(E);continue}break}let C=n.list[a+1];C&&C.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 Za({type:"schema",list:s})}import rt from"fs";import wr from"path";var Ot=[{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 Pr(e){return Ot.find(t=>t.id===e)}var iu=Ot.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ar(e){return rt.existsSync(e)?rt.readFileSync(e,"utf-8"):null}function sc(e,t){let n=wr.join(e,".env.example"),o=Ar(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
+ `);rt.appendFileSync(n,s)}function ic(e,t,n){let o=wr.join(e,".env.example"),r=Ar(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?rt.writeFileSync(o,r.replace(s,`${t}="${n}"`)):rt.appendFileSync(o,`${t}="${n}"
1855
+ `)}async function Cr(e,t,n){let o=Oe(e,"queue");if(t==="none"){o&&rt.rmSync(o,{recursive:!0,force:!0});return}let r=Pr(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${Ot.map(s=>s.id).join(", ")}`);o&&(sc(e,r),ic(e,"QUEUE_PROVIDER",t))}import fe from"fs";import Ce from"path";import{fileURLToPath as ac}from"url";var cc=ac(import.meta.url),Ir=Ce.dirname(cc),pc=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|toml|py)$/,lc=["backends/gateway","infra","e2e","tests"];function dc(){let e=[Ce.join(Ir,"..","templates"),Ce.join(Ir,"..","..","templates")];for(let t of e)if(fe.existsSync(t))return t;return e[0]}async function xr(e,t){let n=dc(),o=[],r=[],s=[...lc,...t.withWorkflows?["workflows"]:[],...t.withPythonBackend?["backends/python"]:[]];for(let i of s){let a=Ce.join(n,i);if(!fe.existsSync(a)){r.push(i);continue}let c=Ce.join(e,i);Rr(a,c),Tr(c,{"{PRODUCT_NAME}":t.projectName}),o.push(i)}return{applied:o,skipped:r}}function Rr(e,t){fe.mkdirSync(t,{recursive:!0});for(let n of fe.readdirSync(e,{withFileTypes:!0})){let o=Ce.join(e,n.name),r=Ce.join(t,n.name);n.isDirectory()?Rr(o,r):fe.existsSync(r)||fe.copyFileSync(o,r)}}function Tr(e,t){for(let n of fe.readdirSync(e,{withFileTypes:!0})){let o=Ce.join(e,n.name);if(n.isDirectory()){Tr(o,t);continue}if(!pc.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 st from"fs";import Nr from"path";var Lt=[{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 kr(e){return Lt.find(t=>t.id===e)}var Su=Lt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Or(e){return st.existsSync(e)?st.readFileSync(e,"utf-8"):null}function uc(e,t){let n=Nr.join(e,".env.example"),o=Or(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
+ `);st.appendFileSync(n,s)}function mc(e,t,n){let o=Nr.join(e,".env.example"),r=Or(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?st.writeFileSync(o,r.replace(s,`${t}="${n}"`)):st.appendFileSync(o,`${t}="${n}"
1857
+ `)}async function Lr(e,t,n){let o=Oe(e,"search");if(t==="none"){o&&st.rmSync(o,{recursive:!0,force:!0});return}let r=kr(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${Lt.map(s=>s.id).join(", ")}`);o&&(uc(e,r),mc(e,"SEARCH_PROVIDER",t))}import Ie from"fs";import $e from"path";function gc(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(Ie.existsSync(o))return{packageDir:n,seedPath:$e.join(n,"prisma","seed.ts"),packageJsonPath:$e.join(n,"package.json")}}return null}function fc(e){try{let t=Ie.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 yc(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 ac(e,t){let n=t.has("Tenant"),o=t.has("User"),r=t.has("Project"),s=ic(e,o),i=n?` let tenants: Array<{ id: string; name: string }> = [];
1888
+ }`}function Sc(e,t){let n=t.has("Tenant"),o=t.has("User"),r=t.has("Project"),s=yc(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 cc(e){if(we.existsSync(e))try{let t=we.readFileSync(e,"utf8"),n=JSON.parse(t),o=n.scripts??{},r=!1;o["db:seed"]||(o["db:seed"]="prisma db seed",r=!0);let s=n.prisma??{};if(s.seed||(s.seed="tsx prisma/seed.ts",r=!0),!r)return;let i={...n,scripts:o,prisma:s};we.writeFileSync(e,JSON.stringify(i,null,2)+`
1958
- `)}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`[create-sailor] Failed to patch seed scripts in ${e}: ${n}`)}}async function xr(e,t){let n=rc(e);if(n)try{let o=Me.join(n.packageDir,"prisma","schema.prisma"),r=sc(o),s=ac(t,r),i=Me.dirname(n.seedPath);we.existsSync(i)||we.mkdirSync(i,{recursive:!0}),we.writeFileSync(n.seedPath,s),cc(n.packageJsonPath)}catch(o){let r=o instanceof Error?o.message:String(o);throw console.error(`[create-sailor] Failed to generate seed data: ${r}`),new Error(`Unable to write prisma/seed.ts: ${r}`)}}import Ae from"fs";import Fe from"path";var kt=[{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:""}],fu=kt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Rr(e){return kt.find(t=>t.id===e)}var pc="@nebutra/sms",lc={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 hn(e,t){Ae.mkdirSync(Fe.dirname(e),{recursive:!0}),Ae.writeFileSync(e,t)}function dc(e,t){let n=Fe.join(e,".env.example");Ae.existsSync(n)?Ae.appendFileSync(n,`
1959
- `+t):Ae.writeFileSync(n,t)}function uc(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
1957
+ `}function hc(e){if(Ie.existsSync(e))try{let t=Ie.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};Ie.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 Ur(e,t){let n=gc(e);if(n)try{let o=$e.join(n.packageDir,"prisma","schema.prisma"),r=fc(o),s=Sc(t,r),i=$e.dirname(n.seedPath);Ie.existsSync(i)||Ie.mkdirSync(i,{recursive:!0}),Ie.writeFileSync(n.seedPath,s),hc(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 xe from"fs";import Ve from"path";var Ut=[{id:"twilio",name:"Twilio",region:"global",envVars:["TWILIO_ACCOUNT_SID","TWILIO_AUTH_TOKEN","TWILIO_FROM_NUMBER"],docs:"https://www.twilio.com/docs/sms",pkgs:["twilio"]},{id:"messagebird",name:"MessageBird (Bird)",region:"global",envVars:["MESSAGEBIRD_ACCESS_KEY","MESSAGEBIRD_ORIGINATOR"],docs:"https://developers.messagebird.com/api/sms-messaging/",pkgs:["messagebird"]},{id:"plivo",name:"Plivo",region:"global",envVars:["PLIVO_AUTH_ID","PLIVO_AUTH_TOKEN","PLIVO_FROM_NUMBER"],docs:"https://www.plivo.com/docs/sms/",pkgs:["plivo"]},{id:"aliyun-sms",name:"\u963F\u91CC\u4E91\u77ED\u4FE1 Aliyun SMS",region:"cn",envVars:["ALIYUN_SMS_ACCESS_KEY","ALIYUN_SMS_ACCESS_SECRET","ALIYUN_SMS_SIGN_NAME","ALIYUN_SMS_TEMPLATE_CODE","ALIYUN_SMS_ENDPOINT"],docs:"https://help.aliyun.com/product/44282.html",pkgs:["@alicloud/dysmsapi20170525","@alicloud/openapi-client"]},{id:"tencent-sms",name:"\u817E\u8BAF\u4E91\u77ED\u4FE1 Tencent SMS",region:"cn",envVars:["TENCENT_SMS_SECRET_ID","TENCENT_SMS_SECRET_KEY","TENCENT_SMS_SDK_APP_ID","TENCENT_SMS_SIGN_NAME","TENCENT_SMS_TEMPLATE_ID","TENCENT_SMS_REGION"],docs:"https://cloud.tencent.com/document/product/382",pkgs:["tencentcloud-sdk-nodejs-sms"]},{id:"yunpian",name:"\u4E91\u7247 Yunpian",region:"cn",envVars:["YUNPIAN_API_KEY","YUNPIAN_SIGN"],docs:"https://www.yunpian.com/official/document/sms/zh_CN/introduction_product_intro",pkgs:["yunpian-nodejs-sdk"]},{id:"none",name:"None",region:"both",envVars:[],docs:""}],Iu=Ut.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Dr(e){return Ut.find(t=>t.id===e)}var Ec="@nebutra/sms",vc={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 _n(e,t){xe.mkdirSync(Ve.dirname(e),{recursive:!0}),xe.writeFileSync(e,t)}function bc(e,t){let n=Ve.join(e,".env.example");xe.existsSync(n)?xe.appendFileSync(n,`
1959
+ `+t):xe.writeFileSync(n,t)}function _c(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 mc=`/**
1962
+ `}var Pc=`/**
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 gc(){return`import twilio from "twilio";
1982
+ `;function wc(){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 fc(){return`import messagebird from "messagebird";
2017
+ `}function Ac(){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 yc(){return`import plivo from "plivo";
2055
+ `}function Cc(){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 Sc(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2094
+ `}function Ic(){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 hc(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2143
+ `}function xc(){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 Ec(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2208
+ `}function Rc(){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 vc(e){switch(e){case"twilio":return gc();case"messagebird":return fc();case"plivo":return yc();case"aliyun-sms":return Sc();case"tencent-sms":return hc();case"yunpian":return Ec();case"none":return`export {};
2261
- `}}function bc(e){let t={};for(let o of e.pkgs??[]){let r=lc[o];r&&(t[o]=r)}let n={name:pc,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 Tr(e,t,n="global"){if(t==="none")return;let o=Rr(t);if(!o)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${kt.map(i=>i.id).join(", ")}`);let r=Fe.join(e,"packages","sms");if(!Ae.existsSync(r))return;let s=Fe.join(r,"src");Ae.existsSync(s)&&Ae.rmSync(s,{recursive:!0,force:!0});try{hn(Fe.join(r,"package.json"),bc(o)),hn(Fe.join(s,"types.ts"),mc),hn(Fe.join(s,"index.ts"),vc(o.id)),dc(e,uc(o))}catch(i){throw console.error(`Failed to apply SMS selection "${t}":`,i),new Error(`SMS scaffold for "${t}" failed \u2014 see stderr for details.`)}}import Be from"fs";import je from"path";var Ve="@nebutra/storage";function En(e,t){Be.mkdirSync(je.dirname(e),{recursive:!0}),Be.writeFileSync(e,t)}function _c(e,t){let n=je.join(e,".env.example");Be.existsSync(n)?Be.appendFileSync(n,`
2263
- `+t):Be.writeFileSync(n,t)}function Pc(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
2260
+ `}function Tc(e){switch(e){case"twilio":return wc();case"messagebird":return Ac();case"plivo":return Cc();case"aliyun-sms":return Ic();case"tencent-sms":return xc();case"yunpian":return Rc();case"none":return`export {};
2261
+ `}}function kc(e){let t={};for(let o of e.pkgs??[]){let r=vc[o];r&&(t[o]=r)}let n={name:Ec,version:"0.1.0",private:!0,description:`Transactional SMS via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
2262
+ `}async function Mr(e,t,n="global"){if(t==="none")return;let o=Dr(t);if(!o)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${Ut.map(i=>i.id).join(", ")}`);let r=Ve.join(e,"packages","sms");if(!xe.existsSync(r))return;let s=Ve.join(r,"src");xe.existsSync(s)&&xe.rmSync(s,{recursive:!0,force:!0});try{_n(Ve.join(r,"package.json"),kc(o)),_n(Ve.join(s,"types.ts"),Pc),_n(Ve.join(s,"index.ts"),Tc(o.id)),bc(e,_c(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 Ye from"fs";import Ke from"path";var qe="@nebutra/storage";function Pn(e,t){Ye.mkdirSync(Ke.dirname(e),{recursive:!0}),Ye.writeFileSync(e,t)}function Nc(e,t){let n=Ke.join(e,".env.example");Ye.existsSync(n)?Ye.appendFileSync(n,`
2263
+ `+t):Ye.writeFileSync(n,t)}function Oc(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 wc=`/**
2266
+ `}var Lc=`/**
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,8 +2289,8 @@ export interface SignedUrlOptions {
2289
2289
  operation?: "get" | "put";
2290
2290
  contentType?: string;
2291
2291
  }
2292
- `;function Ac(){return`/**
2293
- * @${Ve.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
2292
+ `;function Uc(){return`/**
2293
+ * @${qe.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
2294
2294
  *
2295
2295
  * Docs: https://developers.cloudflare.com/r2/api/s3/api/
2296
2296
  */
@@ -2353,8 +2353,8 @@ export async function getSignedUrl(
2353
2353
  }
2354
2354
 
2355
2355
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2356
- `}function Ic(){return`/**
2357
- * @${Ve.slice(1)} \u2014 AWS S3 wrapper.
2356
+ `}function Dc(){return`/**
2357
+ * @${qe.slice(1)} \u2014 AWS S3 wrapper.
2358
2358
  *
2359
2359
  * Docs: https://docs.aws.amazon.com/s3/
2360
2360
  */
@@ -2418,8 +2418,8 @@ export async function getSignedUrl(
2418
2418
  }
2419
2419
 
2420
2420
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2421
- `}function Cc(){return`/**
2422
- * @${Ve.slice(1)} \u2014 Supabase Storage wrapper.
2421
+ `}function Mc(){return`/**
2422
+ * @${qe.slice(1)} \u2014 Supabase Storage wrapper.
2423
2423
  *
2424
2424
  * Docs: https://supabase.com/docs/guides/storage
2425
2425
  */
@@ -2481,8 +2481,8 @@ export async function getSignedUrl(
2481
2481
  }
2482
2482
 
2483
2483
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2484
- `}function xc(){return`/**
2485
- * @${Ve.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2484
+ `}function Fc(){return`/**
2485
+ * @${qe.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2486
2486
  *
2487
2487
  * Docs: https://help.aliyun.com/product/31815.html
2488
2488
  */
@@ -2528,8 +2528,8 @@ export async function getSignedUrl(
2528
2528
  }
2529
2529
 
2530
2530
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2531
- `}function Rc(){return`/**
2532
- * @${Ve.slice(1)} \u2014 \u817E\u8BAF\u4E91 COS wrapper via cos-nodejs-sdk-v5.
2531
+ `}function jc(){return`/**
2532
+ * @${qe.slice(1)} \u2014 \u817E\u8BAF\u4E91 COS wrapper via cos-nodejs-sdk-v5.
2533
2533
  *
2534
2534
  * Docs: https://cloud.tencent.com/document/product/436
2535
2535
  */
@@ -2583,8 +2583,8 @@ export async function getSignedUrl(
2583
2583
  }
2584
2584
 
2585
2585
  export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
2586
- `}function Tc(){return`/**
2587
- * @${Ve.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2586
+ `}function Bc(){return`/**
2587
+ * @${qe.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2588
2588
  *
2589
2589
  * Docs: https://developer.qiniu.com/kodo
2590
2590
  */
@@ -2651,9 +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 Ac();case"s3":return Ic();case"supabase-storage":return Cc();case"aliyun-oss":return xc();case"tencent-cos":return Rc();case"qiniu":return Tc();case"none":return`export {};
2655
- `}}function Nc(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),(e.id==="r2"||e.id==="s3")&&(t["@aws-sdk/s3-request-presigner"]="^3.658.0");let n={name:Ve,version:"0.1.0",private:!0,description:`Object storage via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
2656
- `}async function kr(e,t,n){if(t==="none")return;let o=kn(t);if(!o)throw new Error(`Unknown storage provider "${t}". Valid ids: ${it.map(i=>i.id).join(", ")}`);let r=je.join(e,"packages","storage"),s=je.join(r,"src");Be.existsSync(s)&&Be.rmSync(s,{recursive:!0,force:!0}),En(je.join(r,"package.json"),Nc(o)),En(je.join(s,"types.ts"),wc),En(je.join(s,"index.ts"),kc(o.id)),_c(e,Pc(o))}var Nt=[{id:"svix",name:"Svix",region:"global",envVars:["SVIX_API_TOKEN"],docs:"https://docs.svix.com",description:"Managed webhooks platform"},{id:"custom",name:"Custom (self-hosted)",region:"both",envVars:["WEBHOOK_SIGNING_SECRET"],docs:"",description:"Custom implementation with built-in package"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Nr(e){return Nt.find(t=>t.id===e)}var Au=Nt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Or(e,t,n="global"){let o=Nr(t);if(!o)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Nt.map(r=>r.id).join(", ")}`);if(o.id==="none"){z(e,"webhooks");return}o.envVars.length>0&&oe(e,{category:"Webhooks",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"WEBHOOKS_PROVIDER",o.id)}import $e from"fs";import mt from"path";function Oc(e){return`import { brand } from "@nebutra/brand/metadata";
2654
+ `}function $c(e){switch(e){case"r2":return Uc();case"s3":return Dc();case"supabase-storage":return Mc();case"aliyun-oss":return Fc();case"tencent-cos":return jc();case"qiniu":return Bc();case"none":return`export {};
2655
+ `}}function Vc(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:qe,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 Fr(e,t,n){if(t==="none")return;let o=Fn(t);if(!o)throw new Error(`Unknown storage provider "${t}". Valid ids: ${lt.map(i=>i.id).join(", ")}`);let r=Ke.join(e,"packages","storage"),s=Ke.join(r,"src");Ye.existsSync(s)&&Ye.rmSync(s,{recursive:!0,force:!0}),Pn(Ke.join(r,"package.json"),Vc(o)),Pn(Ke.join(s,"types.ts"),Lc),Pn(Ke.join(s,"index.ts"),$c(o.id)),Nc(e,Oc(o))}var Dt=[{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 jr(e){return Dt.find(t=>t.id===e)}var Mu=Dt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Br(e,t,n="global"){let o=jr(t);if(!o)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Dt.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 Ge from"fs";import St from"path";function Kc(e){return`import { brand } from "@nebutra/brand/metadata";
2657
2657
  import Link from "next/link";
2658
2658
 
2659
2659
  export default function WelcomePage() {
@@ -2763,21 +2763,21 @@ function Step({
2763
2763
  </li>
2764
2764
  );
2765
2765
  }
2766
- `}function Lc(e={}){return`
2766
+ `}function Yc(e={}){return`
2767
2767
  ## What you can do next
2768
2768
 
2769
2769
  ${[e.apiKeys===!1?"- Manage API keys at `/settings/api-keys` (disabled \u2014 re-enable with `--api-keys=true`)":"- Manage API keys at `/settings/api-keys`",e.auditLog===!1?"- View audit log at `/settings/audit-log` (disabled \u2014 re-enable with `--audit-log=true`)":"- View audit log at `/settings/audit-log`","- Configure webhooks at `/settings/webhooks`",e.commandPalette===!1?"- Press \u2318K to open the command palette (disabled \u2014 re-enable with `--command-palette=true`)":"- Press \u2318K to open the command palette","- Edit notification preferences at `/settings/notifications`","- Export your data at `/settings/account/export`","- For China deployments, see `packages/ops/china-compliance/README.md`"].join(`
2770
2770
  `)}
2771
- `}function Uc(e=[]){return e.length===0?"":`
2771
+ `}function qc(e=[]){return e.length===0?"":`
2772
2772
  ## Production readiness holds
2773
2773
 
2774
2774
  Do not enable these in production until provider credentials, adapter wiring, and the integration contract are verified:
2775
2775
 
2776
- ${e.map(n=>{let o=Xe(n.status);return`- ${n.flag}=${n.provider} ${o} \u2014 ${Ee(n.status)}`}).join(`
2776
+ ${e.map(n=>{let o=Qe(n.status);return`- ${n.flag}=${n.provider} ${o} \u2014 ${_e(n.status)}`}).join(`
2777
2777
  `)}
2778
2778
 
2779
2779
  Review the package readiness matrix before handoff: [docs/package-status.md](docs/package-status.md)
2780
- `}function Dc(e,t,n=[],o={}){return`# Next steps \u2014 ${e}
2780
+ `}function Gc(e,t,n=[],o={}){return`# Next steps \u2014 ${e}
2781
2781
 
2782
2782
  Region: ${t}
2783
2783
 
@@ -2803,27 +2803,27 @@ Your AI-native SaaS scaffold is ready. Complete these four steps to go from temp
2803
2803
  \`\`\`
2804
2804
 
2805
2805
  After setup, delete the welcome route at \`apps/web/src/app/[locale]/welcome/\`.
2806
- ${Lc(o)}${Uc(n)}
2806
+ ${Yc(o)}${qc(n)}
2807
2807
 
2808
2808
  ## Resources
2809
2809
 
2810
2810
  - [Documentation](/docs)
2811
2811
  - [GitHub](https://github.com/nebutra/nebutra-sailor)
2812
2812
  - [Get free license (Individual/OPC)](https://nebutra.com/get-license)
2813
- `}async function Lr(e,t){let{projectName:n,region:o,previewSelections:r=[],waveFeatures:s={}}=t;try{let i=mt.join(e,".sailor");$e.existsSync(i)||$e.mkdirSync(i,{recursive:!0}),$e.writeFileSync(mt.join(i,"next-steps.md"),Dc(n,o,r,s))}catch(i){let a=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write .sailor/next-steps.md: ${a}`)}try{let i=mt.join(e,"apps","web");if(!$e.existsSync(i))return;let a=mt.join(i,"src","app","[locale]","welcome");$e.existsSync(a)||$e.mkdirSync(a,{recursive:!0}),$e.writeFileSync(mt.join(a,"page.tsx"),Oc(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 Ur(e){return e!==null&&typeof e=="object"&&"code"in e&&e.code==="ENOENT"}function Fc(e,t){for(let n of t)if(e)l(!0,{event:"warn",step:n.flag,provider:n.provider,packageStatus:n.status,message:Ee(n.status)});else{let o=Xe(n.status);process.stdout.write(gt.yellow(`\u26A0 ${n.flag}=${n.provider} ${o} \u2014 ${Ee(n.status)}
2815
- `))}}function jc(e,t,n){let o=Ke.join(t,"packages/platform/db/prisma/schema.prisma"),r;try{r=Lt.readFileSync(o,"utf8")}catch(s){if(Ur(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=Sn(r,n);Lt.writeFileSync(o,s),yn(Ke.join(Ke.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 Dr(e){let{resolvedTarget:t,projectName:n,resolvedPm:o,opts:r,useJson:s,resolved:i,startedAt:a}=e,{region:c,orm:p,database:u,databaseHost:d,payment:A,paymentChoice:b,auth:f,socialLoginIds:h,aiProviders:S,deployTarget:m,docs:_,metering:G,billingMode:D,idp:fe,accessGate:pe,mcp:Z,waveToggles:j,previewSelections:$,config:C}=i,H={auth:f,payment:b,"billing-mode":D,idp:fe,template:"saas","access-gate":pe};l(s,{event:"step",step:"clone",status:"start"}),await jo(t),l(s,{event:"step",step:"clone",status:"ok"}),l(s,{event:"step",step:"package",status:"start"}),await er(t,n),l(s,{event:"step",step:"package",status:"ok"}),l(s,{event:"step",step:"config",status:"start"}),await mo(t,C),l(s,{event:"step",step:"config",status:"ok"}),l(s,{event:"step",step:"governance-lints",status:"start"});let le=await Vo(t,C);l(s,{event:"step",step:"governance-lints",status:"ok",lints:le.lints}),l(s,{event:"step",step:"prune",status:"start"}),await ur(t,C),l(s,{event:"step",step:"prune",status:"ok"});{let E=Ke.join(t,"packages/platform/db/prisma/schema.prisma"),T;try{T=Lt.readFileSync(E,"utf-8")}catch(I){if(Ur(I))l(s,{event:"step",step:"schema-prune",status:"skip"});else{let x=I instanceof Error?I.message:String(I);l(s,{event:"step",step:"schema-prune",status:"error",error:x})}}if(T!==void 0){l(s,{event:"step",step:"schema-prune",status:"start"});try{let I=Sn(T,H);Lt.writeFileSync(E,I),yn(Ke.join(Ke.dirname(E),"migrations"),H),l(s,{event:"step",step:"schema-prune",status:"ok"})}catch(I){let x=I instanceof Error?I.message:String(I);l(s,{event:"step",step:"schema-prune",status:"error",error:x})}}}if(l(s,{event:"step",step:"auth",choice:f,status:"start"}),await eo(t,f),l(s,{event:"step",step:"auth",choice:f,status:"ok"}),h.length>0?(l(s,{event:"step",step:"social-login",providers:h,status:"start"}),await no(t,h,f),l(s,{event:"step",step:"social-login",providers:h,status:"ok"})):l(s,{event:"step",step:"social-login",status:"skip"}),l(s,{event:"step",step:"db",choice:u,status:"start"}),await yo(t,u,n),u!=="none"){let E=st(d);E&&(await So(t,E,n),l(s,{event:"step",step:"db-host",choice:d,status:"ok"}))}if(l(s,{event:"step",step:"db",choice:u,status:"ok"}),p==="drizzle"){l(s,{event:"step",step:"orm",choice:"drizzle",status:"start"});let E=await or(t,"drizzle",u);l(s,{event:"step",step:"orm",choice:"drizzle",status:E.applied?"ok":"skip",...E.reason?{reason:E.reason}:{}})}if(l(s,{event:"step",step:"payment",choice:b,status:"start"}),await sr(t,b),l(s,{event:"step",step:"payment",choice:b,status:"ok"}),await wo(t,i.email,c),s&&l(!0,{event:"step",step:"email",choice:i.email,status:"ok"}),await kr(t,i.storage,c),s&&l(!0,{event:"step",step:"storage",choice:i.storage,status:"ok"}),await Jo(t,i.monitoring,c),s&&l(!0,{event:"step",step:"monitoring",choice:i.monitoring,status:"ok"}),await Qn(t,i.analytics,c),s&&l(!0,{event:"step",step:"analytics",choice:i.analytics,status:"ok"}),await Tr(t,i.sms,c),s&&l(!0,{event:"step",step:"sms",choice:i.sms,status:"ok"}),await Er(t,i.queue,c),s&&l(!0,{event:"step",step:"queue",choice:i.queue,status:"ok"}),await Cr(t,i.search,c),s&&l(!0,{event:"step",step:"search",choice:i.search,status:"ok"}),await io(t,i.cache,c),s&&l(!0,{event:"step",step:"cache",choice:i.cache,status:"ok"}),await Zo(t,i.notifications,c),s&&l(!0,{event:"step",step:"notifications",choice:i.notifications,status:"ok"}),await Or(t,i.webhooks,c),s&&l(!0,{event:"step",step:"webhooks",choice:i.webhooks,status:"ok"}),await lo(t,i.cms,c),s&&l(!0,{event:"step",step:"cms",choice:i.cms,status:"ok"}),await No(t,i.featureFlags,c),s&&l(!0,{event:"step",step:"feature-flags",choice:i.featureFlags,status:"ok"}),await co(t,i.captcha,c),s&&l(!0,{event:"step",step:"captcha",choice:i.captcha,status:"ok"}),await Go(t,Z),s&&l(!0,{event:"step",step:"mcp",mode:Z,status:"ok"}),await Wo(t,G,A),s&&l(!0,{event:"step",step:"metering",mode:G,status:"ok"}),l(s,{event:"step",step:"prune-wave-features",status:"start"}),mr(t,j),l(s,{event:"step",step:"prune-wave-features",status:"ok",toggles:j}),C.orm==="prisma"&&C.database!=="none"?jc(s,t,H):l(s,{event:"step",step:"schema-prune",status:"skip"}),l(s,{event:"step",step:"billing-mode",choice:D,status:"ok"}),l(s,{event:"step",step:"idp",choice:fe,status:"ok"}),await uo(t,c),s&&l(!0,{event:"step",step:"compliance",region:c,status:"ok"}),await To(t),await xr(t,f),await Lr(t,{projectName:n,region:c,previewSelections:$,waveFeatures:j}),C.aiMode!=="none"){l(s,{event:"step",step:"ai-providers",status:"start"});let E={providerIds:C.aiProviders,customEndpoint:C.customAiEndpoint},T=Ke.join(t,"packages/ai/ai-providers/templates");await lr(t,E,T),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 vo(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 qn(t,m),await Yn(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 Co(t,P),l(s,{event:"step",step:"env",status:"ok"}),l(s,{event:"step",step:"scaffold-extras",status:"start"});let ye=await br(t,{projectName:n,withWorkflows:!!r.withWorkflows,withPythonBackend:!!r.withPythonBackend});l(s,{event:"step",step:"scaffold-extras",status:"ok",applied:ye.applied,skipped:ye.skipped}),l(s,{event:"step",step:"license",status:"start"});try{let E=qo(t,{projectName:n,cliVersion:X});l(s,{event:"step",step:"license",status:"ok",tier:"mit-scaffold",wrote:E.wrote}),s||process.stdout.write(gt.dim(` License: MIT \u2014 commercial use, closed source, no fee, no attribution.
2813
+ `}async function $r(e,t){let{projectName:n,region:o,previewSelections:r=[],waveFeatures:s={}}=t;try{let i=St.join(e,".sailor");Ge.existsSync(i)||Ge.mkdirSync(i,{recursive:!0}),Ge.writeFileSync(St.join(i,"next-steps.md"),Gc(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=St.join(e,"apps","web");if(!Ge.existsSync(i))return;let a=St.join(i,"src","app","[locale]","welcome");Ge.existsSync(a)||Ge.mkdirSync(a,{recursive:!0}),Ge.writeFileSync(St.join(a,"page.tsx"),Kc(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 Vr(e){return e!==null&&typeof e=="object"&&"code"in e&&e.code==="ENOENT"}function Wc(e,t){for(let n of t)if(e)l(!0,{event:"warn",step:n.flag,provider:n.provider,packageStatus:n.status,message:_e(n.status)});else{let o=Qe(n.status);process.stdout.write(ht.yellow(`\u26A0 ${n.flag}=${n.provider} ${o} \u2014 ${_e(n.status)}
2815
+ `))}}function Xc(e,t,n){let o=He.join(t,"packages/platform/db/prisma/schema.prisma"),r;try{r=Ft.readFileSync(o,"utf8")}catch(s){if(Vr(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=bn(r,n);Ft.writeFileSync(o,s),vn(He.join(He.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 Kr(e){let{resolvedTarget:t,projectName:n,resolvedPm:o,opts:r,useJson:s,resolved:i,startedAt:a}=e,{region:c,orm:p,database:d,databaseHost:m,payment:C,paymentChoice:E,auth:g,socialLoginIds:h,aiProviders:S,deployTarget:u,docs:_,metering:H,billingMode:F,idp:he,accessGate:le,mcp:ee,waveToggles:B,previewSelections:K,config:I}=i,W={auth:g,payment:E,"billing-mode":F,idp:he,template:"saas","access-gate":le};l(s,{event:"step",step:"clone",status:"start"}),await Go(t),l(s,{event:"step",step:"clone",status:"ok"}),l(s,{event:"step",step:"package",status:"start"}),await ar(t,n),l(s,{event:"step",step:"package",status:"ok"}),l(s,{event:"step",step:"config",status:"start"}),await vo(t,I),l(s,{event:"step",step:"config",status:"ok"}),l(s,{event:"step",step:"governance-lints",status:"start"});let de=await Wo(t,I);l(s,{event:"step",step:"governance-lints",status:"ok",lints:de.lints}),l(s,{event:"step",step:"prune",status:"start"}),await Er(t,I),l(s,{event:"step",step:"prune",status:"ok"});{let v=He.join(t,"packages/platform/db/prisma/schema.prisma"),T;try{T=Ft.readFileSync(v,"utf-8")}catch(A){if(Vr(A))l(s,{event:"step",step:"schema-prune",status:"skip"});else{let x=A instanceof Error?A.message:String(A);l(s,{event:"step",step:"schema-prune",status:"error",error:x})}}if(T!==void 0){l(s,{event:"step",step:"schema-prune",status:"start"});try{let A=bn(T,W);Ft.writeFileSync(v,A),vn(He.join(He.dirname(v),"migrations"),W),l(s,{event:"step",step:"schema-prune",status:"ok"})}catch(A){let x=A instanceof Error?A.message:String(A);l(s,{event:"step",step:"schema-prune",status:"error",error:x})}}}if(l(s,{event:"step",step:"auth",choice:g,status:"start"}),await ao(t,g),l(s,{event:"step",step:"auth",choice:g,status:"ok"}),h.length>0?(l(s,{event:"step",step:"social-login",providers:h,status:"start"}),await po(t,h,g),l(s,{event:"step",step:"social-login",providers:h,status:"ok"})):l(s,{event:"step",step:"social-login",status:"skip"}),l(s,{event:"step",step:"db",choice:d,status:"start"}),await Po(t,d,n),d!=="none"){let v=pt(m);v&&(await wo(t,v,n),l(s,{event:"step",step:"db-host",choice:m,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 lr(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:E,status:"start"}),await ur(t,E),l(s,{event:"step",step:"payment",choice:E,status:"ok"}),await ko(t,i.email,c),s&&l(!0,{event:"step",step:"email",choice:i.email,status:"ok"}),await Fr(t,i.storage,c),s&&l(!0,{event:"step",step:"storage",choice:i.storage,status:"ok"}),await rr(t,i.monitoring,c),s&&l(!0,{event:"step",step:"monitoring",choice:i.monitoring,status:"ok"}),await so(t,i.analytics,c),s&&l(!0,{event:"step",step:"analytics",choice:i.analytics,status:"ok"}),await Mr(t,i.sms,c),s&&l(!0,{event:"step",step:"sms",choice:i.sms,status:"ok"}),await Cr(t,i.queue,c),s&&l(!0,{event:"step",step:"queue",choice:i.queue,status:"ok"}),await Lr(t,i.search,c),s&&l(!0,{event:"step",step:"search",choice:i.search,status:"ok"}),await go(t,i.cache,c),s&&l(!0,{event:"step",step:"cache",choice:i.cache,status:"ok"}),await ir(t,i.notifications,c),s&&l(!0,{event:"step",step:"notifications",choice:i.notifications,status:"ok"}),await Br(t,i.webhooks,c),s&&l(!0,{event:"step",step:"webhooks",choice:i.webhooks,status:"ok"}),await ho(t,i.cms,c),s&&l(!0,{event:"step",step:"cms",choice:i.cms,status:"ok"}),await jo(t,i.featureFlags,c),s&&l(!0,{event:"step",step:"feature-flags",choice:i.featureFlags,status:"ok"}),await yo(t,i.captcha,c),s&&l(!0,{event:"step",step:"captcha",choice:i.captcha,status:"ok"}),await Zo(t,ee),s&&l(!0,{event:"step",step:"mcp",mode:ee,status:"ok"}),await tr(t,H,C),s&&l(!0,{event:"step",step:"metering",mode:H,status:"ok"}),l(s,{event:"step",step:"prune-wave-features",status:"start"}),vr(t,B),l(s,{event:"step",step:"prune-wave-features",status:"ok",toggles:B}),I.orm==="prisma"&&I.database!=="none"?Xc(s,t,W):l(s,{event:"step",step:"schema-prune",status:"skip"}),l(s,{event:"step",step:"billing-mode",choice:F,status:"ok"}),l(s,{event:"step",step:"idp",choice:he,status:"ok"}),await Eo(t,c),s&&l(!0,{event:"step",step:"compliance",region:c,status:"ok"}),await Mo(t),await Ur(t,g),await $r(t,{projectName:n,region:c,previewSelections:K,waveFeatures:B}),I.aiMode!=="none"){l(s,{event:"step",step:"ai-providers",status:"start"});let v={providerIds:I.aiProviders,customEndpoint:I.customAiEndpoint},T=He.join(t,"packages/ai/ai-providers/templates");await Sr(t,v,T),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 Io(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"}),u!=="none"&&await Qn(t,u),await Jn(t,I.deployTargets),l(s,{event:"step",step:"deploy-target",status:"ok",targets:I.deployTargets});let P={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""};l(s,{event:"step",step:"env",status:"start"}),await Lo(t,P),l(s,{event:"step",step:"env",status:"ok"}),l(s,{event:"step",step:"scaffold-extras",status:"start"});let Ee=await xr(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=Qo(t,{projectName:n,cliVersion:z});l(s,{event:"step",step:"license",status:"ok",tier:"mit-scaffold",wrote:v.wrote}),s||process.stdout.write(ht.dim(` License: MIT \u2014 commercial use, closed source, no fee, no attribution.
2816
2816
  Upstream terms preserved as LICENSE-UPSTREAM-REFERENCE.md.
2817
- `))}catch(E){l(s,{event:"step",step:"license",status:"warn",message:E instanceof Error?E.message:String(E)})}if(r.install!==!1){let E=o==="bun"?"bun":o,T=["install"];s?l(!0,{event:"step",step:"install",pm:o,status:"start"}):process.stdout.write(gt.dim(` Installing dependencies with ${o}\u2026
2818
- `));try{Ot(E,T,{cwd:t,stdio:s?"ignore":"inherit"}),l(s,{event:"step",step:"install",status:"ok"})}catch(I){let x=I instanceof Error?I.message:String(I);s?l(!0,{event:"step",step:"install",status:"error",error:x}):process.stdout.write(gt.yellow(` \u26A0 install failed \u2014 run '${o} install' manually.
2819
- `))}}else l(s,{event:"step",step:"install",status:"skip"});if(r.git!==!1){s&&l(!0,{event:"step",step:"git-init",status:"start"});try{Ot("git",["init","-q"],{cwd:t,stdio:"ignore"}),Ot("git",["add","-A"],{cwd:t,stdio:"ignore"}),Ot("git",["-c","user.email=you@example.com","-c","user.name=You","commit","-q","-m","chore: initial scaffold from create-sailor"],{cwd:t,stdio:"ignore"}),l(s,{event:"step",step:"git-init",status:"ok"})}catch(E){let T=E instanceof Error?E.message:String(E);s?l(!0,{event:"step",step:"git-init",status:"error",error:T}):process.stdout.write(gt.yellow(` \u26A0 git init skipped \u2014 not fatal.
2820
- `))}}else l(s,{event:"step",step:"git-init",status:"skip"});let Se=Math.max(1,Math.round((Date.now()-a)/1e3));Zn({template_version:X,package_manager:o,region:c,auth:f,payment:b,ai_providers:S,deploy_target:m,duration_ms:Date.now()-a}),$.length>0&&Fc(s,$),s?l(!0,{event:"done",status:"ok",elapsedSec:Se,targetDir:t,previewSelections:$,waveFeatures:j}):Xn({elapsedSec:Se,targetDir:t,skippedInstall:r.install===!1,previewSelections:$,waveFeatures:j});try{Mc({pkg:{name:"create-sailor",version:X},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}}import Bc from"cfonts";import Vc from"picocolors";function Mr(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${X}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
2821
- `));return}Bc.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(Vc.dim(` AI-Native SaaS Template \xB7 v${X} \xB7 nebutra.com
2817
+ `))}catch(v){l(s,{event:"step",step:"license",status:"warn",message:v instanceof Error?v.message:String(v)})}if(r.install!==!1){let v=o==="bun"?"bun":o,T=["install"];s?l(!0,{event:"step",step:"install",pm:o,status:"start"}):process.stdout.write(ht.dim(` Installing dependencies with ${o}\u2026
2818
+ `));try{Mt(v,T,{cwd:t,stdio:s?"ignore":"inherit"}),l(s,{event:"step",step:"install",status:"ok"})}catch(A){let x=A instanceof Error?A.message:String(A);s?l(!0,{event:"step",step:"install",status:"error",error:x}):process.stdout.write(ht.yellow(` \u26A0 install failed \u2014 run '${o} install' manually.
2819
+ `))}}else l(s,{event:"step",step:"install",status:"skip"});if(r.git!==!1){s&&l(!0,{event:"step",step:"git-init",status:"start"});try{Mt("git",["init","-q"],{cwd:t,stdio:"ignore"}),Mt("git",["add","-A"],{cwd:t,stdio:"ignore"}),Mt("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 T=v instanceof Error?v.message:String(v);s?l(!0,{event:"step",step:"git-init",status:"error",error:T}):process.stdout.write(ht.yellow(` \u26A0 git init skipped \u2014 not fatal.
2820
+ `))}}else l(s,{event:"step",step:"git-init",status:"skip"});let ve=Math.max(1,Math.round((Date.now()-a)/1e3));io({template_version:z,package_manager:o,region:c,auth:g,payment:E,ai_providers:S,deploy_target:u,duration_ms:Date.now()-a}),K.length>0&&Wc(s,K),s?l(!0,{event:"done",status:"ok",elapsedSec:ve,targetDir:t,previewSelections:K,waveFeatures:B}):no({elapsedSec:ve,targetDir:t,skippedInstall:r.install===!1,previewSelections:K,waveFeatures:B});try{Hc({pkg:{name:"create-sailor",version:z},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}}import zc from"cfonts";import Jc from"picocolors";function Yr(){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(`
2821
+ `));return}zc.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(Jc.dim(` AI-Native SaaS Template \xB7 v${z} \xB7 nebutra.com
2822
2822
 
2823
- `))}var $c=`Usage: create-sailor [name] [options]
2823
+ `))}var Qc=`Usage: create-sailor [name] [options]
2824
2824
 
2825
2825
  Arguments:
2826
- name project directory (default: ./my-saas-app)
2826
+ name project name or path (default: my-app; use . for cwd)
2827
2827
 
2828
2828
  Core options:
2829
2829
  -p, --pm <id> npm | pnpm | yarn | bun (auto-detected)
@@ -2891,31 +2891,36 @@ Examples:
2891
2891
  $ npx create-sailor@latest my-app --region=cn --auth=clerk
2892
2892
  $ npx create-sailor@latest my-app --region=hybrid --ai=openai,deepseek
2893
2893
  $ npm create sailor@latest --dry-run --region=cn
2894
- `;function Fr(){process.stdout.write($c)}import Ut from"picocolors";function jr(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Kc(e){let t=jr()?"\u25B8":"->",n=`[${e.index}/${e.total}]`,o=e.label.padEnd(18," ");return jr()?`${Ut.dim(n)} ${Ut.bold(o)} ${Ut.dim(t)} ${Ut.cyan(e.value)}`:`${n} ${o} ${t} ${e.value}`}function Br(e){process.stdout.write(Kc(e)+`
2895
- `)}import{existsSync as Yc,mkdirSync as Vr,writeFileSync as $r}from"fs";import{homedir as Kr,platform as qc}from"os";import{join as ft}from"path";function Gc(){if(qc()==="win32"){let t=process.env.LOCALAPPDATA||ft(Kr(),"AppData","Local");return ft(t,"nebutra")}let e=process.env.XDG_CONFIG_HOME;return e?ft(e,"nebutra"):ft(Kr(),".config","nebutra")}function Hc(){let e=process.env.NEBUTRA_TELEMETRY;return e==="0"||e==="false"||e==="no"}function Yr(){if(!process.stderr.isTTY||!process.stdin.isTTY||process.env.CI)return;let e=Gc(),t=ft(e,"first-run-acked");try{if(Yc(t))return}catch{return}if(Hc()){try{Vr(e,{recursive:!0}),$r(t,"")}catch{}return}let n=["[36m\u2139[0m Nebutra collects anonymous usage analytics to improve the scaffolder."," Opt out at any time: export NEBUTRA_TELEMETRY=0"," Privacy policy: https://nebutra.com/legal/cli-analytics",""];try{process.stderr.write(n.join(`
2896
- `))}catch{}try{Vr(e,{recursive:!0}),$r(t,"")}catch{}}function Ye(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2897
- `)}function Xc(e,t,n,o,r){let{region:s,orm:i,database:a,paymentChoice:c,docs:p,socialLoginIds:u,aiMode:d,aiProviders:A,customAiEndpoint:b,deployTarget:f,metering:h,payment:S,billingMode:m,idp:_,mcp:G,waveToggles:D,previewSelections:fe}=t,{email:pe,storage:Z,monitoring:j,analytics:$,sms:C,queue:H,search:le,cache:P,notifications:ye,webhooks:qe,cms:Ge,featureFlags:Se,captcha:E}=t,T=A.length,I=[`clone template \u2192 ${n}`,"write nebutra.config.json",`governance-lints \u2192 write governance.config.json + wire pnpm lint (no-raw-inputs${a!=="none"?" + repository-seam":""})`,`prune template (orm=${i}, i18n=${t.i18n})`,`region \u2192 ${s}`,`auth \u2192 ${t.auth==="none"?"skip (remove packages/auth)":`configure ${t.auth}`}`,...u.length>0?[`social-login \u2192 generate ${u.length} callback route${u.length===1?"":"s"} + SocialLoginButtons.tsx (${u.join(", ")})`]:[],`db \u2192 ${a==="none"?"skip (remove packages/db)":`configure Prisma for ${a}`}`,...a!=="none"?[`db-host \u2192 configure ${t.databaseHost}`]:[],`payment \u2192 ${c==="none"?"skip (remove packages/billing)":`configure ${c}`}`,...p!=="none"?[`docs \u2192 scaffold apps/docs (${p==="fumadocs"?"fumadocs":`${p} \u2192 fumadocs fallback`})`]:[],...T>0||b?[`ai-providers \u2192 generate ${d} registry seed + env (${T}${b?" + custom":""} provider${T===1&&!b?"":"s"})`]:[],...pe!=="none"?[`email \u2192 configure ${pe}`]:[],...Z!=="none"?[`storage \u2192 configure ${Z}`]:[],...j!=="none"?[`monitoring \u2192 configure ${j}`]:[],...$!=="none"?[`analytics \u2192 configure ${$}`]:[],...C!=="none"?[`sms \u2192 configure ${C}`]:[],...H!=="none"?[`queue \u2192 configure ${H}`]:[],...le!=="none"?[`search \u2192 configure ${le}`]:[],...P!=="none"?[`cache \u2192 configure ${P}`]:[],...ye!=="none"?[`notifications \u2192 configure ${ye}`]:[],...qe!=="none"?[`webhooks \u2192 configure ${qe}`]:[],...Ge!=="none"?[`cms \u2192 configure ${Ge}`]:[],...Se!=="none"?[`feature-flags \u2192 configure ${Se}`]:[],...E!=="none"?[`captcha \u2192 configure ${E}`]:[],`mcp \u2192 ${G==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${h==="off"?"disabled":h==="auto"?S!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...m!=="usage"?[`billing-mode \u2192 ${m}`]:[],..._!=="clerk"?[`idp \u2192 ${_}`]:[],`cron-jobs \u2192 ${D.cronJobs?"enabled":"disabled"}`,`audit-log \u2192 ${D.auditLog?"enabled":"disabled"}`,`api-keys \u2192 ${D.apiKeys?"enabled":"disabled"}`,`command-palette \u2192 ${D.commandPalette?"enabled":"disabled"}`,`cookie-consent \u2192 ${D.cookieConsent?"enabled":"disabled"}`,`legal-pages \u2192 ${D.legalPages?"enabled":"disabled"}`,`china-compliance \u2192 ${D.chinaCompliance?"enabled (@nebutra/china-compliance + ICP footer)":"disabled"}`,`compliance \u2192 inject ${s} boilerplate (ICP/Cookie/AIGC/Privacy)`,"welcome \u2192 generate dev welcome page","env \u2192 generate random secrets (AUTH_SECRET, JWT_SECRET)","seed \u2192 generate prisma/seed.ts (1 admin + 3 tenants)",...f!=="none"?[`deploy \u2192 inject ${f} config`]:[],"inject .env.local",r.install===!1?"skip install":`run ${o} install`,r.git===!1?"skip git init":"run git init"];if(e){for(let x of I)Ye(!0,{event:"plan",action:x});for(let x of fe)Ye(!0,{event:"warn",step:x.flag,provider:x.provider,packageStatus:x.status});Ye(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2898
- `+F.bold(`Dry run \u2014 planned actions:
2899
- `));for(let x of I)process.stdout.write(` \u2022 ${x}
2900
- `);if(fe.length>0){process.stdout.write(`
2901
- `+F.bold(F.yellow(`Preview-status providers selected:
2902
- `)));for(let x of fe)process.stdout.write(F.yellow(`\u26A0 ${x.flag}=${x.provider}
2903
- `))}process.stdout.write(F.dim(`
2894
+ `;function qr(){process.stdout.write(Qc)}import jt from"picocolors";function Gr(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Zc(e){let t=Gr()?"\u25B8":"->",n=`[${e.index}/${e.total}]`,o=e.label.padEnd(18," ");return Gr()?`${jt.dim(n)} ${jt.bold(o)} ${jt.dim(t)} ${jt.cyan(e.value)}`:`${n} ${o} ${t} ${e.value}`}function Hr(e){process.stdout.write(Zc(e)+`
2895
+ `)}import{existsSync as ep,mkdirSync as Wr,writeFileSync as Xr}from"fs";import{homedir as zr,platform as tp}from"os";import{join as Et}from"path";function np(){if(tp()==="win32"){let t=process.env.LOCALAPPDATA||Et(zr(),"AppData","Local");return Et(t,"nebutra")}let e=process.env.XDG_CONFIG_HOME;return e?Et(e,"nebutra"):Et(zr(),".config","nebutra")}function op(){let e=process.env.NEBUTRA_TELEMETRY;return e==="0"||e==="false"||e==="no"}function Jr(){if(!process.stderr.isTTY||!process.stdin.isTTY||process.env.CI)return;let e=np(),t=Et(e,"first-run-acked");try{if(ep(t))return}catch{return}if(op()){try{Wr(e,{recursive:!0}),Xr(t,"")}catch{}return}let n=["[36m\u2139[0m Nebutra collects anonymous usage analytics to improve the scaffolder."," Opt out at any time: export NEBUTRA_TELEMETRY=0"," Privacy policy: https://nebutra.com/legal/cli-analytics",""];try{process.stderr.write(n.join(`
2896
+ `))}catch{}try{Wr(e,{recursive:!0}),Xr(t,"")}catch{}}import at from"fs";import ye from"path";import*as M from"@clack/prompts";var Se="my-app",rp=new Set([".DS_Store",".Spotlight-V100",".Trashes","Thumbs.db","desktop.ini"]),Qr=new Set(["package.json","node_modules","pnpm-workspace.yaml","pnpm-lock.yaml","yarn.lock","package-lock.json","bun.lockb","turbo.json"]);function Cn(e){let t=e.trim();return t==="."||t==="./"||t===".\\"}function wn(e){if(!at.existsSync(e))return!0;let t;try{t=at.readdirSync(e)}catch{return!1}return t.every(n=>rp.has(n)||n===".git")}function An(e){if(!at.existsSync(e))return!1;let t;try{t=at.readdirSync(e)}catch{return!0}return t.some(n=>Qr.has(n))}function sp(e=process.cwd()){return wn(e)&&!An(e)}function Zr(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(!Cn(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 it(e,t=process.cwd()){let n=e.trim()||Se;if(Cn(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=Zr(n);if(r)throw new Error(r);let s=`./${n}`,i=ye.resolve(t,n);return{targetDir:s,projectName:n,absoluteDir:i}}async function es(e={}){let t=e.cwd??process.cwd(),n=e.onCancel??(()=>{process.stdout.write(`Cancelled
2897
+ `),process.exit(130)}),o=sp(t),r=ye.basename(t)||t,s=await M.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(M.isCancel(s)&&n(),s==="current"){if(An(t)){let c=at.readdirSync(t).filter(p=>Qr.has(p)).slice(0,4).join(", ");M.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(!wn(t)){let c=await M.confirm({message:"Current directory is not empty. Scaffold files will be mixed in \u2014 continue?",initialValue:!1});(M.isCancel(c)||!c)&&n()}return it(".",t)}let i=await M.text({message:"What should we call your project?",placeholder:Se,defaultValue:Se,validate:c=>{let p=(c??"").trim()||Se;if(Cn(p)||/[\\/]/.test(p)||ye.isAbsolute(p))try{it(p,t);return}catch(d){return d instanceof Error?d.message:"Invalid path."}return Zr(p)}});M.isCancel(i)&&n();let a=it(String(i).trim()||Se,t);if(at.existsSync(a.absoluteDir)&&!wn(a.absoluteDir)){An(a.absoluteDir)&&(M.log.error(`Folder "${a.projectName}" already exists and looks like a project. Pick another name.`),n());let c=await M.confirm({message:`Folder "${a.projectName}" is not empty. Continue?`,initialValue:!1});(M.isCancel(c)||!c)&&n()}return a}function Re(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2898
+ `)}function ap(e,t,n,o,r){let{region:s,orm:i,database:a,paymentChoice:c,docs:p,socialLoginIds:d,aiMode:m,aiProviders:C,customAiEndpoint:E,deployTarget:g,metering:h,payment:S,billingMode:u,idp:_,mcp:H,waveToggles:F,previewSelections:he}=t,{email:le,storage:ee,monitoring:B,analytics:K,sms:I,queue:W,search:de,cache:P,notifications:Ee,webhooks:We,cms:Xe,featureFlags:ve,captcha:v}=t,T=C.length,A=[`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`})`]:[],...T>0||E?[`ai-providers \u2192 generate ${m} registry seed + env (${T}${E?" + custom":""} provider${T===1&&!E?"":"s"})`]:[],...le!=="none"?[`email \u2192 configure ${le}`]:[],...ee!=="none"?[`storage \u2192 configure ${ee}`]:[],...B!=="none"?[`monitoring \u2192 configure ${B}`]:[],...K!=="none"?[`analytics \u2192 configure ${K}`]:[],...I!=="none"?[`sms \u2192 configure ${I}`]:[],...W!=="none"?[`queue \u2192 configure ${W}`]:[],...de!=="none"?[`search \u2192 configure ${de}`]:[],...P!=="none"?[`cache \u2192 configure ${P}`]:[],...Ee!=="none"?[`notifications \u2192 configure ${Ee}`]:[],...We!=="none"?[`webhooks \u2192 configure ${We}`]:[],...Xe!=="none"?[`cms \u2192 configure ${Xe}`]:[],...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 ${h==="off"?"disabled":h==="auto"?S!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...u!=="usage"?[`billing-mode \u2192 ${u}`]:[],..._!=="clerk"?[`idp \u2192 ${_}`]:[],`cron-jobs \u2192 ${F.cronJobs?"enabled":"disabled"}`,`audit-log \u2192 ${F.auditLog?"enabled":"disabled"}`,`api-keys \u2192 ${F.apiKeys?"enabled":"disabled"}`,`command-palette \u2192 ${F.commandPalette?"enabled":"disabled"}`,`cookie-consent \u2192 ${F.cookieConsent?"enabled":"disabled"}`,`legal-pages \u2192 ${F.legalPages?"enabled":"disabled"}`,`china-compliance \u2192 ${F.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 x of A)Re(!0,{event:"plan",action:x});for(let x of he)Re(!0,{event:"warn",step:x.flag,provider:x.provider,packageStatus:x.status});Re(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2899
+ `+D.bold(`Dry run \u2014 planned actions:
2900
+ `));for(let x of A)process.stdout.write(` \u2022 ${x}
2901
+ `);if(he.length>0){process.stdout.write(`
2902
+ `+D.bold(D.yellow(`Preview-status providers selected:
2903
+ `)));for(let x of he)process.stdout.write(D.yellow(`\u26A0 ${x.flag}=${x.provider}
2904
+ `))}process.stdout.write(D.dim(`
2904
2905
  No files were written.
2905
- `))}}async function zc(){let e=Rn();e.parse(process.argv);let t=e.opts(),[n]=e.args;t.help&&(Fr(),process.exit(0));let o=!!t.json,r=!!t.dryRun,s=!!t.yes,i=s||!process.stdin.isTTY;if(o||(Yr(),Mr()),Ye(o,{event:"start",version:X}),!t.pm)try{Wc("pnpm --version",{stdio:"ignore"})}catch{o||process.stderr.write(`
2906
- ${F.red("\u2718")} ${F.bold("pnpm is required")} but was not found on PATH.
2906
+ `))}}async function cp(){let e=Dn();e.parse(process.argv);let t=e.opts(),[n]=e.args;t.help&&(qr(),process.exit(0));let o=!!t.json,r=!!t.dryRun,i=!!t.yes||!process.stdin.isTTY;if(o||(Jr(),Yr()),Re(o,{event:"start",version:z}),!t.pm)try{ip("pnpm --version",{stdio:"ignore"})}catch{o||process.stderr.write(`
2907
+ ${D.red("\u2718")} ${D.bold("pnpm is required")} but was not found on PATH.
2907
2908
 
2908
2909
  The scaffold uses pnpm workspaces + Turborepo. Install pnpm first:
2909
- ${F.cyan("npm i -g pnpm@10")}
2910
+ ${D.cyan("npm i -g pnpm@10")}
2910
2911
 
2911
- Then retry: ${F.cyan("pnpm dlx create-sailor@latest")}
2912
- (or pass ${F.dim("--pm=npm")} if you know workspace:* won't resolve in your setup)
2912
+ Then retry: ${D.cyan("pnpm dlx create-sailor@latest")}
2913
+ (or pass ${D.dim("--pm=npm")} if you know workspace:* won't resolve in your setup)
2913
2914
 
2914
- `),Ye(o,{event:"error",code:"PNPM_MISSING"}),process.exit(1)}let a=n??(s?"./my-saas-app":void 0),c;if(a)c=a;else if(i)c="./my-saas-app";else{let f=await ot.group({name:()=>ot.text({message:"Where should we create your project?",placeholder:"./my-saas-app",defaultValue:"./my-saas-app",validate:h=>{if(!h?.length)return"Please enter a path."}})},{onCancel:()=>{process.stdout.write(F.red(`\u2718 Cancelled
2915
- `)),process.exit(130)}});c=String(f.name)}let p=Gr.basename(Gr.resolve(c)),u=t.pm??Ln(),d=await Wn(t,o),A=[["Project name",p],["Region",d.region],["Auth",d.auth],["Social login",d.socialLoginIds.length>0?d.socialLoginIds.map(f=>We.find(h=>h.id===f)?.name??f).join(", "):"none"],["ORM",d.orm],["Database",d.database],["Database Host",d.databaseHost],["Payment",d.paymentChoice],["AI topology",`${d.aiMode}${d.aiProviders.length>0?` (${d.aiProviders.join(", ")} seed)`:""}${d.customAiEndpoint?" + custom endpoint":""}`],["Email",d.email],["Storage",d.storage],["Monitoring",d.monitoring],["Analytics",d.analytics],["SMS",d.sms],["Deploy Target",d.deployTarget],["Docs Framework",d.docs],["Access gate",d.accessGate]];o?A.forEach(([f,h],S)=>{Ye(!0,{event:"step",step:f,value:h,index:S+1,total:A.length})}):A.forEach(([f,h],S)=>{Br({index:S+1,total:A.length,label:f,value:h})}),r&&(Xc(o,d,c,u,t),process.exit(0));let b=async()=>{process.stdout.write(`
2916
- `+F.red(`\u2718 Cancelled
2917
- `)),qr.existsSync(c)&&await ot.confirm({message:`Cleanup partial install at ${c}?`,initialValue:!0})===!0&&(qr.rmSync(c,{recursive:!0,force:!0}),process.stdout.write(F.dim(` \u2713 Removed ${c}
2918
- `))),process.exit(130)};process.on("SIGINT",b);try{await Dr({resolvedTarget:c,projectName:p,resolvedPm:u,opts:t,useJson:o,resolved:d,startedAt:Date.now()}),process.exit(0)}catch(f){let h=f instanceof Error?f.message:String(f);o?Ye(!0,{event:"error",message:h}):process.stdout.write(F.red(`
2915
+ `),Re(o,{event:"error",code:"PNPM_MISSING"}),process.exit(1)}let a=()=>{process.stdout.write(D.red(`\u2718 Cancelled
2916
+ `)),process.exit(130)},c,p;if(n)try{let g=it(n);c=g.targetDir,p=g.projectName}catch(g){let h=g instanceof Error?g.message:String(g);process.stderr.write(`
2917
+ ${D.red("\u2718")} ${h}
2918
+
2919
+ `),Re(o,{event:"error",code:"INVALID_PROJECT_NAME",message:h}),process.exit(1)}else if(i){let g=it(Se);c=g.targetDir,p=g.projectName}else{let g=await es({onCancel:a});c=g.targetDir,p=g.projectName,o||process.stdout.write(D.dim(` \u2192 ${g.absoluteDir}
2920
+ `))}let d=t.pm??$n(),m=await to(t,o),C=[["Project name",p],["Region",m.region],["Auth",m.auth],["Social login",m.socialLoginIds.length>0?m.socialLoginIds.map(g=>Je.find(h=>h.id===g)?.name??g).join(", "):"none"],["ORM",m.orm],["Database",m.database],["Database Host",m.databaseHost],["Payment",m.paymentChoice],["AI topology",`${m.aiMode}${m.aiProviders.length>0?` (${m.aiProviders.join(", ")} seed)`:""}${m.customAiEndpoint?" + custom endpoint":""}`],["Email",m.email],["Storage",m.storage],["Monitoring",m.monitoring],["Analytics",m.analytics],["SMS",m.sms],["Deploy Target",m.deployTarget],["Docs Framework",m.docs],["Access gate",m.accessGate]];o?C.forEach(([g,h],S)=>{Re(!0,{event:"step",step:g,value:h,index:S+1,total:C.length})}):C.forEach(([g,h],S)=>{Hr({index:S+1,total:C.length,label:g,value:h})}),r&&(ap(o,m,c,d,t),process.exit(0));let E=async()=>{process.stdout.write(`
2921
+ `+D.red(`\u2718 Cancelled
2922
+ `)),ts.existsSync(c)&&await ns.confirm({message:`Cleanup partial install at ${c}?`,initialValue:!0})===!0&&(ts.rmSync(c,{recursive:!0,force:!0}),process.stdout.write(D.dim(` \u2713 Removed ${c}
2923
+ `))),process.exit(130)};process.on("SIGINT",E);try{await Kr({resolvedTarget:c,projectName:p,resolvedPm:d,opts:t,useJson:o,resolved:m,startedAt:Date.now()}),process.exit(0)}catch(g){let h=g instanceof Error?g.message:String(g);o?Re(!0,{event:"error",message:h}):process.stdout.write(D.red(`
2919
2924
  \u2718 Failed: ${h}
2920
- `)),process.exit(1)}}zc().catch(e=>{process.stderr.write(String(e)+`
2925
+ `)),process.exit(1)}}cp().catch(e=>{process.stderr.write(String(e)+`
2921
2926
  `),process.exit(1)});