create-sailor 1.9.3 → 1.9.4

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 +8 -1
  2. package/dist/index.js +213 -199
  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 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(`
2
+ import{a as Fn}from"./chunk-PA4CKDRJ.js";import"./chunk-IYWUY3VA.js";import{execSync as mp}from"child_process";import os from"fs";import*as rs from"@clack/prompts";import L from"picocolors";import{Command as ps}from"commander";import jn from"fs";import Jt from"path";import{fileURLToPath as as}from"url";function cs(){try{let t=Jt.dirname(as(import.meta.url));for(let n=0;n<4;n++){let o=Jt.join(t,"package.json");if(jn.existsSync(o)){let r=jn.readFileSync(o,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=Jt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var z=cs();var ls="create-sailor";function Bn(){let e=new ps;return e.name(ls).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(z,"-v, --version").helpOption(!1).argument("[name]","project name or path (default: my-app; use . for current directory)",void 0).option("-p, --pm <id>","npm | pnpm | yarn | bun").option("--region <id>","global | cn | hybrid").option("--orm <id>","prisma (default, primary) | drizzle (dual-ORM: adds db-drizzle alongside Prisma \u2014 Postgres only)").option("--db <id>","postgres | mysql | sqlite | none \u2014 engine (Prisma provider)").option("--db-host <id>","local | supabase | neon | vercel-postgres | planetscale | railway | aliyun-rds | tencent-cdb | none \u2014 managed-provider (region default: supabase global, local cn)").option("--auth <id>","clerk | betterauth | nextauth | supabase | none").option("--social-login <ids>","CN social login providers \u2014 wechat | qq | dingtalk | workweixin | feishu | weibo (comma-separated)").option("--payment <id>","stripe | lemon | wechat | alipay | none").option("--ai <mode-or-ids>","topology shorthand (gateway | direct | custom | none) OR comma-separated provider ids (e.g. openai,anthropic)").option("--deploy <target>","vercel | railway | cloudflare | selfhost").option("--docs <id>","fumadocs | mintlify | docusaurus | nextra | vitepress | none").option("--email <id>","resend | postmark | ses | aliyun-dm | tencent-ses | netease | none").option("--storage <id>","r2 | s3 | supabase-storage | aliyun-oss | tencent-cos | qiniu | none").option("--monitoring <id>","sentry | datadog | aliyun-arms | tingyun | none").option("--analytics <id>","posthog | plausible | umami | baidu | sensors | none").option("--sms <id>","twilio | aliyun-sms | tencent-sms | yunpian | none").option("--queue <id>","qstash | bullmq | sqs | none").option("--search <id>","meilisearch | typesense | algolia | pgvector | none").option("--cache <id>","upstash-redis | vercel-kv | redis | dragonfly | none").option("--notifications <id>","novu | knock | custom | none").option("--webhooks <id>","svix | custom | none").option("--cms <id>","sanity | contentful | strapi | none").option("--feature-flags <id>","vercel-flags | growthbook | configcat | none").option("--captcha <id>","turnstile | hcaptcha | aliyun-slide | none").option("--mcp <mode>","on | off (default: on)").option("--metering <mode>","auto | on | off (default: auto \u2014 auto-on when payment is set)").option("--billing-mode <mode>","usage | seat | credits (default: usage)").option("--idp <id>","clerk | oauth-server (default: clerk)").option("--access-gate <mode>","none | invite (default: none)").option("--cron-jobs <bool>","true | false \u2014 scaffold scheduled cron handlers (default: true)").option("--audit-log <bool>","true | false \u2014 enable /settings/audit-log + arch test (default: false \u2014 @nebutra/audit is WIP)").option("--api-keys <bool>","true | false \u2014 enable /settings/api-keys page (default: true)").option("--command-palette <bool>","true | false \u2014 enable \u2318K command palette (default: true)").option("--cookie-consent <bool>","true | false \u2014 enable GDPR/CCPA cookie banner (default: true)").option("--legal-pages <bool>","true | false \u2014 enable dynamic /legal/[slug] route (default: true)").option("--china-compliance <bool>","true | false \u2014 enable @nebutra/china-compliance + ICP footer (default: true when --region=cn, otherwise false)").option("--i18n","enable i18n").option("--no-i18n","disable i18n").option("--with-workflows","scaffold workflows/ (inngest + n8n + pusher stubs)").option("--with-python-backend","scaffold backends/python/ (FastAPI stub \u2014 only when TS-by-Default ADR exception applies)").option("--no-install","skip package install").option("--no-git","skip git init").option("-y, --yes","accept all defaults (non-interactive)").option("--dry-run","preview actions without writing files").option("--json","machine-readable output").option("--no-color","disable color output").option("-h, --help","show help"),e}import Kn from"picocolors";var Qt=[{id:"local",name:"Local / Self-hosted Docker",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres:postgres@localhost:5432/$PROJECT",comment:"Local Postgres via docker-compose (pnpm infra:up)"}],docs:"https://www.postgresql.org/docs/",description:"Docker on localhost. You operate it.",tier:"self-hosted"},{id:"supabase",name:"Supabase",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:5432/postgres?sslmode=require",comment:"Supabase session pooler \u2014 use for runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://postgres:<password>@db.<project-ref>.supabase.co:5432/postgres?sslmode=require",comment:"Supabase direct \u2014 use for Prisma migrations"},{name:"NEXT_PUBLIC_SUPABASE_URL",placeholder:"https://<project>.supabase.co"},{name:"NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY",placeholder:""},{name:"NEXT_PUBLIC_SUPABASE_ANON_KEY",placeholder:""},{name:"SUPABASE_PUBLISHABLE_KEY",placeholder:""},{name:"SUPABASE_SERVICE_ROLE_KEY",placeholder:""}],docs:"https://supabase.com/docs",description:"Managed Postgres + auth/storage/realtime/edge-functions.",tier:"managed"},{id:"neon",name:"Neon",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>-pooler.<region>.neon.tech/<db>?sslmode=require",comment:"Neon pooled \u2014 runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>.<region>.neon.tech/<db>?sslmode=require",comment:"Neon direct (no -pooler) \u2014 migrations"}],docs:"https://neon.tech/docs",description:"Serverless Postgres with branching and scale-to-zero.",tier:"managed"},{id:"vercel-postgres",name:"Vercel Postgres",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"$POSTGRES_PRISMA_URL",comment:"Vercel Marketplace injects POSTGRES_PRISMA_URL automatically"},{name:"DIRECT_URL",placeholder:"$POSTGRES_URL_NON_POOLING",comment:"Vercel Marketplace injects POSTGRES_URL_NON_POOLING automatically"}],docs:"https://vercel.com/docs/storage/vercel-postgres",description:"Neon-backed, auto-provisioned via Vercel Marketplace.",tier:"managed"},{id:"planetscale",name:"PlanetScale Postgres",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres.<branch-id>:<password>@<host>.horizon.psdb.cloud:6432/postgres?sslmode=require",comment:"PlanetScale Postgres pooled/PgBouncer URL \u2014 runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://postgres.<branch-id>:<password>@<host>.horizon.psdb.cloud:5432/postgres?sslmode=require",comment:"PlanetScale Postgres direct URL \u2014 Prisma migrations"}],docs:"https://planetscale.com/docs/postgres",description:"Managed Postgres with branching; compatible with Sailor migrations.",tier:"managed"},{id:"railway",name:"Railway",region:"global",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"$DATABASE_URL",comment:"Railway service env var; injected when you link a Postgres service"}],docs:"https://docs.railway.app/databases/postgresql",description:"Generalist managed infra; standard TCP Postgres/MySQL.",tier:"managed"},{id:"aliyun-rds",name:"Aliyun RDS",region:"cn",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@<rds-instance>.rds.aliyuncs.com:5432/<db>",comment:"Aliyun RDS Postgres \u2014 internal VPC endpoint recommended"}],docs:"https://www.alibabacloud.com/help/en/rds",description:"Aliyun RDS \u2014 China compliance + intranet routing.",tier:"managed"},{id:"tencent-cdb",name:"Tencent CloudDB (CDB)",region:"cn",supportedEngines:["mysql","postgresql"],envVars:[{name:"DATABASE_URL",placeholder:"mysql://<user>:<pwd>@<cdb-instance>.tencentcdb.com:3306/<db>",comment:"Tencent CloudDB \u2014 VPC endpoint recommended"}],docs:"https://intl.cloud.tencent.com/document/product/236",description:"Tencent CloudDB \u2014 China compliance.",tier:"managed"},{id:"none",name:"None",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[],docs:"",description:"Skip database scaffolding.",tier:"self-hosted"}];function mt(e){return Qt.find(t=>t.id===e)}function Vn(e){return e==="cn"||e==="hybrid"?"local":"supabase"}var Re=[{id:"r2",name:"Cloudflare R2",region:"global",envVars:["R2_ACCOUNT_ID","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY","R2_BUCKET"],docs:"https://developers.cloudflare.com/r2/api/s3/api/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"s3",name:"AWS S3",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_S3_REGION","S3_BUCKET"],docs:"https://docs.aws.amazon.com/s3/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"supabase-storage",name:"Supabase Storage",region:"global",envVars:["SUPABASE_URL","SUPABASE_SERVICE_ROLE_KEY","SUPABASE_BUCKET"],docs:"https://supabase.com/docs/guides/storage",pkg:"@supabase/supabase-js",pkgVersion:"^2.45.4"},{id:"aliyun-oss",name:"\u963F\u91CC\u4E91 OSS",region:"cn",envVars:["ALIYUN_OSS_ACCESS_KEY","ALIYUN_OSS_ACCESS_SECRET","ALIYUN_OSS_REGION","ALIYUN_OSS_BUCKET"],docs:"https://help.aliyun.com/product/31815.html",pkg:"ali-oss",pkgVersion:"^6.21.0"},{id:"tencent-cos",name:"\u817E\u8BAF\u4E91 COS",region:"cn",envVars:["TENCENT_COS_SECRET_ID","TENCENT_COS_SECRET_KEY","TENCENT_COS_BUCKET","TENCENT_COS_REGION"],docs:"https://cloud.tencent.com/document/product/436",pkg:"cos-nodejs-sdk-v5",pkgVersion:"^2.13.7"},{id:"qiniu",name:"\u4E03\u725B\u4E91 Kodo",region:"cn",envVars:["QINIU_ACCESS_KEY","QINIU_SECRET_KEY","QINIU_BUCKET","QINIU_DOMAIN"],docs:"https://developer.qiniu.com/kodo",pkg:"qiniu",pkgVersion:"^7.14.0"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function Zt(e){let t=e==="supabase"?"supabase-storage":e;return Re.some(n=>n.id===t)?t:void 0}function $n(e){let t=Zt(e);return t?Re.find(n=>n.id===t):void 0}var wp=Re.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function qn(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function en(e){switch(e){case"postgres":case"postgresql":return"postgresql";case"mysql":return"mysql";case"sqlite":return"sqlite";case"none":return"none";default:return"postgresql"}}function tn(e,t,n){let o=e?.trim().toLowerCase()??Vn(t),r=mt(o);if(!r){let i=Qt.map(a=>a.id).join(", ");throw new Error(`Unknown --db-host="${o}". Valid: ${i}`)}let s=n;return r.forcedEngine&&s!=="none"&&s!==r.forcedEngine&&(s=r.forcedEngine),{hostId:r.id,engine:s}}function nn(e){return e==="drizzle"?"drizzle":"prisma"}function gt(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function ft(e){if(!e)return"stripe";let t=e.toLowerCase();return t==="lemon"||t==="lemonsqueezy"?"lemon":t==="wechat"?"wechat":t==="alipay"?"alipay":t==="none"?"none":"stripe"}function on(e){if(!e)return"clerk";let t=e.toLowerCase();return t==="betterauth"||t==="better-auth"?"betterauth":t==="nextauth"||t==="next-auth"||t==="authjs"||t==="auth.js"?"nextauth":t==="supabase"||t==="supabase-auth"?"supabase":t==="none"?"none":"clerk"}var ds=new Set(["gateway","direct","custom","none"]);function rn(e){if(!e)return!1;let t=e.trim().toLowerCase();return ds.has(t)}function sn(e){if(!e)return["openai"];if(rn(e))return[];let t=e.split(",").map(n=>n.trim().toLowerCase());return t.includes("none")?[]:t}function Gn(e,t){let n=e??t;return Zt(n)??n}var Yn={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function an(e,t){if(!e)return"fumadocs";let n=e.toLowerCase();if(n==="fumadocs"||n==="none")return n;if(n in Yn){let o=Yn[n];return t?process.stdout.write(JSON.stringify({event:"notice",kind:"docs-fallback",requested:n,effective:"fumadocs"})+`
3
+ `):process.stdout.write(Kn.yellow(`\u26A0 ${o} support is coming in v1.2. Falling back to fumadocs.
4
+ `)+Kn.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
5
+ `)),"fumadocs"}return"fumadocs"}function yt(e){switch(e){case"vercel":return"vercel";case"railway":return"railway";case"cloudflare":return"cloudflare";case"selfhost":return"selfhost";case"none":return"none";default:return"vercel"}}function cn(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function Hn(e){return{...e==="cn"?{email:"aliyun-dm",storage:"aliyun-oss",monitoring:"sentry",analytics:"baidu",sms:"aliyun-sms"}:e==="hybrid"?{email:"resend",storage:"aliyun-oss",monitoring:"sentry",analytics:"posthog",sms:"aliyun-sms"}:{email:"resend",storage:"r2",monitoring:"sentry",analytics:"posthog",sms:"twilio"},queue:"none",search:"none",cache:e==="global"?"upstash-redis":e==="cn"?"redis":"upstash-redis",notifications:"none",webhooks:"none",cms:"none",featureFlags:"none",captcha:"none",mcp:"on",metering:"auto",billingMode:"usage",idp:"clerk",accessGate:"none"}}function pn(e){return e==="cn"?"wechat":"stripe"}import*as q from"@clack/prompts";import Ts from"picocolors";var ln=[{id:"anthropic",name:"Anthropic",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://docs.anthropic.com",envVarPrefix:"ANTHROPIC",requiredEnvVars:["ANTHROPIC_API_KEY"]},{id:"openai",name:"OpenAI",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.openai.com/docs",envVarPrefix:"OPENAI",requiredEnvVars:["OPENAI_API_KEY"]},{id:"deepseek",name:"DeepSeek",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.deepseek.com/api-docs",envVarPrefix:"DEEPSEEK",requiredEnvVars:["DEEPSEEK_API_KEY"]},{id:"xai",name:"xAI (Grok)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://docs.x.ai/api",envVarPrefix:"XAI",requiredEnvVars:["XAI_API_KEY"]},{id:"moonshot",name:"Moonshot (Kimi)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.moonshot.cn/docs",envVarPrefix:"MOONSHOT",requiredEnvVars:["MOONSHOT_API_KEY","MOONSHOT_BASE_URL"]},{id:"google",name:"Google Gemini",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://ai.google.dev/gemini-api/docs",envVarPrefix:"GOOGLE_GENERATIVE_AI",requiredEnvVars:["GOOGLE_GENERATIVE_AI_API_KEY"]},{id:"mistral",name:"Mistral AI",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://docs.mistral.ai",envVarPrefix:"MISTRAL",requiredEnvVars:["MISTRAL_API_KEY"]},{id:"cohere",name:"Cohere",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://docs.cohere.com",envVarPrefix:"COHERE",requiredEnvVars:["COHERE_API_KEY"]},{id:"perplexity",name:"Perplexity",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://docs.perplexity.ai",baseURL:"https://api.perplexity.ai",envVarPrefix:"PERPLEXITY",requiredEnvVars:["PERPLEXITY_API_KEY"]},{id:"ai21",name:"AI21 Labs",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://docs.ai21.com",baseURL:"https://api.ai21.com/studio/v1",envVarPrefix:"AI21",requiredEnvVars:["AI21_API_KEY"]},{id:"upstage",name:"Upstage (Solar)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://developers.upstage.ai/docs",baseURL:"https://api.upstage.ai/v1/solar",envVarPrefix:"UPSTAGE",requiredEnvVars:["UPSTAGE_API_KEY"]},{id:"siliconflow",name:"\u7845\u57FA\u6D41\u52A8 SiliconFlow",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://docs.siliconflow.cn",baseURL:"https://api.siliconflow.cn/v1",envVarPrefix:"SILICONFLOW",requiredEnvVars:["SILICONFLOW_API_KEY"]},{id:"volcengine-ark",name:"\u706B\u5C71\u5F15\u64CE ARK (\u8C46\u5305)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://www.volcengine.com/docs/82379",baseURL:"https://ark.cn-beijing.volces.com/api/v3",envVarPrefix:"ARK",requiredEnvVars:["ARK_API_KEY"]},{id:"bailian",name:"\u767E\u70BC Bailian (\u901A\u4E49)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://help.aliyun.com/zh/model-studio",baseURL:"https://dashscope.aliyuncs.com/compatible-mode/v1",envVarPrefix:"DASHSCOPE",requiredEnvVars:["DASHSCOPE_API_KEY"]},{id:"zhipu",name:"\u667A\u8C31 AI Zhipu",category:"\u56FD\u5185\u5E73\u53F0",status:"ai-sdk",docs:"https://docs.bigmodel.cn",baseURL:"https://open.bigmodel.cn/api/paas/v4",envVarPrefix:"ZHIPU",requiredEnvVars:["ZHIPU_API_KEY"]},{id:"baichuan",name:"\u767E\u5DDD\u667A\u80FD Baichuan",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.baichuan-ai.com/docs",baseURL:"https://api.baichuan-ai.com/v1",envVarPrefix:"BAICHUAN",requiredEnvVars:["BAICHUAN_API_KEY"]},{id:"minimax",name:"MiniMax (ABAB)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.minimaxi.com/document/guides",baseURL:"https://api.minimax.chat/v1",envVarPrefix:"MINIMAX",requiredEnvVars:["MINIMAX_API_KEY","MINIMAX_GROUP_ID"]},{id:"stepfun",name:"\u9636\u8DC3\u661F\u8FB0 StepFun",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.stepfun.com/docs",baseURL:"https://api.stepfun.com/v1",envVarPrefix:"STEPFUN",requiredEnvVars:["STEPFUN_API_KEY"]},{id:"sensetime",name:"\u5546\u6C64 SenseNova",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.sensenova.cn/docs",baseURL:"https://token.sensenova.cn/v1",envVarPrefix:"SENSENOVA",requiredEnvVars:["SENSENOVA_API_KEY"]},{id:"tencent",name:"\u817E\u8BAF\u6DF7\u5143 Hunyuan",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://cloud.tencent.com/document/product/1729",baseURL:"https://api.hunyuan.cloud.tencent.com/v1",envVarPrefix:"HUNYUAN",requiredEnvVars:["HUNYUAN_API_KEY"]},{id:"lingyi",name:"\u96F6\u4E00\u4E07\u7269 Yi",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.lingyiwanwu.com/docs",baseURL:"https://api.lingyiwanwu.com/v1",envVarPrefix:"YI",requiredEnvVars:["YI_API_KEY"]},{id:"openrouter",name:"OpenRouter",category:"\u7EDF\u4E00\u7F51\u5173",status:"opencode",docs:"https://openrouter.ai/docs",envVarPrefix:"OPENROUTER",requiredEnvVars:["OPENROUTER_API_KEY"]},{id:"vercel-gateway",name:"Vercel AI Gateway",category:"\u7EDF\u4E00\u7F51\u5173",status:"opencode",docs:"https://vercel.com/docs/ai-gateway",envVarPrefix:"AI_GATEWAY",requiredEnvVars:["AI_GATEWAY_API_KEY"]},{id:"litellm",name:"LiteLLM Proxy",category:"\u7EDF\u4E00\u7F51\u5173",status:"cn-compatible",docs:"https://docs.litellm.ai",baseURL:"http://localhost:4000/v1",envVarPrefix:"LITELLM",requiredEnvVars:["LITELLM_API_KEY"]},{id:"portkey",name:"Portkey",category:"\u7EDF\u4E00\u7F51\u5173",status:"cn-compatible",docs:"https://portkey.ai/docs",baseURL:"https://api.portkey.ai/v1",envVarPrefix:"PORTKEY",requiredEnvVars:["PORTKEY_API_KEY"]},{id:"aws-bedrock",name:"AWS Bedrock",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://aws.amazon.com/bedrock/",envVarPrefix:"AWS_BEDROCK",requiredEnvVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_REGION"]},{id:"azure-openai",name:"Azure OpenAI",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://azure.microsoft.com/en-us/products/cognitive-services/openai-service/",envVarPrefix:"AZURE_OPENAI",requiredEnvVars:["AZURE_OPENAI_API_KEY","AZURE_OPENAI_ENDPOINT"]},{id:"gcp-vertex",name:"GCP Vertex AI",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://cloud.google.com/vertex-ai",envVarPrefix:"GOOGLE_VERTEX",requiredEnvVars:["GOOGLE_APPLICATION_CREDENTIALS"]},{id:"groq",name:"Groq",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://console.groq.com/docs",envVarPrefix:"GROQ",requiredEnvVars:["GROQ_API_KEY"]},{id:"fireworks",name:"Fireworks AI",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://docs.fireworks.ai",envVarPrefix:"FIREWORKS",requiredEnvVars:["FIREWORKS_API_KEY"]},{id:"together",name:"Together AI",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://docs.together.ai",envVarPrefix:"TOGETHER",requiredEnvVars:["TOGETHER_API_KEY"]},{id:"huggingface",name:"Hugging Face",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://huggingface.co/docs/inference-providers",envVarPrefix:"HF",requiredEnvVars:["HF_API_KEY"]},{id:"replicate",name:"Replicate",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://replicate.com/docs",envVarPrefix:"REPLICATE",requiredEnvVars:["REPLICATE_API_TOKEN"]},{id:"lepton",name:"Lepton AI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://www.lepton.ai/docs",baseURL:"https://api.lepton.ai/v1",envVarPrefix:"LEPTON",requiredEnvVars:["LEPTON_API_KEY"]},{id:"anyscale",name:"Anyscale Endpoints",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://docs.endpoints.anyscale.com/",baseURL:"https://api.endpoints.anyscale.com/v1",envVarPrefix:"ANYSCALE",requiredEnvVars:["ANYSCALE_API_KEY"]},{id:"octoai",name:"OctoAI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://octoai.cloud/docs",baseURL:"https://text.octoai.run/v1",envVarPrefix:"OCTOAI",requiredEnvVars:["OCTOAI_TOKEN"]},{id:"deepinfra",name:"DeepInfra",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://deepinfra.com/docs",baseURL:"https://api.deepinfra.com/v1/openai",envVarPrefix:"DEEPINFRA",requiredEnvVars:["DEEPINFRA_API_KEY"]},{id:"novita",name:"Novita AI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://novita.ai/docs",baseURL:"https://api.novita.ai/v3/openai",envVarPrefix:"NOVITA",requiredEnvVars:["NOVITA_API_KEY"]},{id:"black-forest-labs",name:"Black Forest Labs (FLUX)",category:"\u591A\u6A21\u6001",status:"ai-sdk",docs:"https://docs.bfl.ml",envVarPrefix:"BFL",requiredEnvVars:["BFL_API_KEY"]},{id:"elevenlabs",name:"ElevenLabs (TTS)",category:"\u591A\u6A21\u6001",status:"ai-sdk",docs:"https://elevenlabs.io/docs",envVarPrefix:"ELEVENLABS",requiredEnvVars:["ELEVENLABS_API_KEY"]},{id:"runway",name:"Runway (Video)",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://runwayml.com",envVarPrefix:"RUNWAY",requiredEnvVars:["RUNWAY_API_KEY"]},{id:"luma",name:"Luma (Video)",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://lumalabs.ai",envVarPrefix:"LUMA",requiredEnvVars:["LUMA_API_KEY"]},{id:"midjourney",name:"Midjourney",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://docs.midjourney.com",envVarPrefix:"MIDJOURNEY",requiredEnvVars:[]},{id:"ollama",name:"Ollama (\u672C\u5730)",category:"\u672C\u5730\u90E8\u7F72",status:"opencode",docs:"https://github.com/ollama/ollama",baseURL:"http://localhost:11434/v1",envVarPrefix:"OLLAMA",requiredEnvVars:["OLLAMA_BASE_URL"]},{id:"lmstudio",name:"LM Studio",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://lmstudio.ai/docs",baseURL:"http://localhost:1234/v1",envVarPrefix:"LMSTUDIO",requiredEnvVars:[]},{id:"vllm",name:"vLLM",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://docs.vllm.ai",baseURL:"http://localhost:8000/v1",envVarPrefix:"VLLM",requiredEnvVars:[]},{id:"tgi",name:"HF TGI",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://huggingface.co/docs/text-generation-inference",baseURL:"http://localhost:8080/v1",envVarPrefix:"TGI",requiredEnvVars:[]}],Tp=ln.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var us=["openai","anthropic","google"],ms=["openai"];function dn(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let n=t.length>0?t:[...us];return{mode:"gateway",providerIds:n,customEndpoint:e.customEndpoint,routing:{profile:"multi-provider-gateway",providerSeed:n,runtimeGovernance:!0}}}case"direct":{let n=t.length>0?t:[...ms];return{mode:"direct",providerIds:n,customEndpoint:e.customEndpoint,routing:{profile:"direct-adapters",providerSeed:n,runtimeGovernance:!1}}}case"custom":return{mode:"custom",providerIds:t,customEndpoint:e.customEndpoint,routing:{profile:"openai-compatible",providerSeed:t,runtimeGovernance:!0}};case"none":return{mode:"none",providerIds:[],routing:{profile:"disabled",providerSeed:[],runtimeGovernance:!1}}}}var Ze=[{id:"wechat",name:"\u5FAE\u4FE1\u5F00\u653E\u5E73\u53F0",region:"cn",envVars:["WECHAT_APP_ID","WECHAT_APP_SECRET"],docs:"https://open.weixin.qq.com/cgi-bin/showdocument",callbackUrl:"/api/auth/callback/wechat",tokenEndpoint:"https://api.weixin.qq.com/sns/oauth2/access_token"},{id:"qq",name:"QQ \u767B\u5F55",region:"cn",envVars:["QQ_APP_ID","QQ_APP_KEY"],docs:"https://wiki.connect.qq.com",callbackUrl:"/api/auth/callback/qq",tokenEndpoint:"https://graph.qq.com/oauth2.0/token"},{id:"dingtalk",name:"\u9489\u9489",region:"cn",envVars:["DINGTALK_APP_ID","DINGTALK_APP_SECRET"],docs:"https://open.dingtalk.com/document/",callbackUrl:"/api/auth/callback/dingtalk",tokenEndpoint:"https://api.dingtalk.com/v1.0/oauth2/userAccessToken"},{id:"workweixin",name:"\u4F01\u4E1A\u5FAE\u4FE1",region:"cn",envVars:["WORKWEIXIN_CORP_ID","WORKWEIXIN_AGENT_ID","WORKWEIXIN_SECRET"],docs:"https://developer.work.weixin.qq.com",callbackUrl:"/api/auth/callback/workweixin",tokenEndpoint:"https://qyapi.weixin.qq.com/cgi-bin/gettoken"},{id:"feishu",name:"\u98DE\u4E66 / Lark",region:"cn",envVars:["FEISHU_APP_ID","FEISHU_APP_SECRET"],docs:"https://open.feishu.cn/document/",callbackUrl:"/api/auth/callback/feishu",tokenEndpoint:"https://open.feishu.cn/open-apis/authen/v1/access_token"},{id:"weibo",name:"\u5FAE\u535A",region:"cn",envVars:["WEIBO_APP_KEY","WEIBO_APP_SECRET"],docs:"https://open.weibo.com/wiki/",callbackUrl:"/api/auth/callback/weibo",tokenEndpoint:"https://api.weibo.com/oauth2/access_token"}],gs=new Set(Ze.map(e=>e.id));function Wn(e){return Ze.find(t=>t.id===e)}function Xn(e){if(!e)return[];let t=e.split(",").map(r=>r.trim().toLowerCase()).filter(Boolean);if(t.includes("none"))return[];let n=[],o=new Set;for(let r of t)gs.has(r)&&!o.has(r)&&(n.push(r),o.add(r));return n}import te from"fs";import T from"path";import{fileURLToPath as bs}from"url";var zn=["web","landing","auth","admin","design-docs","sailor-docs","router","forge","typelens","gateway","python-ai"],fs={web:"frontend",landing:"frontend",auth:"frontend",admin:"frontend","design-docs":"frontend","sailor-docs":"frontend",router:"frontend",forge:"frontend",typelens:"frontend",gateway:"edgeGateway","python-ai":"originBackend"},ys={frontend:"vercel",edgeGateway:"cloudflare-workers",originBackend:"ecs-docker"};function Ss(e){return zn.includes(e)}function hs(e){if(!Ss(e))throw new Error(`Unknown deploy service '${e}'. Deploy targets apply only to apps/backends, not packages.`)}function Es(e){return hs(e),fs[e]}function vs(e){let t=Es(e);return ys[t]}function Jn(){return Object.fromEntries(zn.map(e=>[e,vs(e)]))}var _s=bs(import.meta.url),Qn=T.dirname(_s),Ps="cloudflare-pages",ws="standalone",As="railway";function un(e,t,n,o){return{...e,web:t,landing:t,auth:t,admin:t,"design-docs":t,"sailor-docs":t,router:t,forge:t,typelens:t,gateway:n,"python-ai":o}}function Cs(){let e=[T.join(Qn,"..","templates","deploy"),T.join(Qn,"..","..","templates","deploy")];for(let t of e)if(te.existsSync(t))return t;return e[0]}function Ct(e){let t=Jn();switch(e){case"cloudflare":return un(t,Ps,"cloudflare-workers","ecs-docker");case"selfhost":return un(t,ws,"ecs-docker","ecs-docker");case"railway":return un(t,As,"railway","railway");case"none":case"vercel":return t}}function Is(e){return`DEPLOY_TARGET_${e.toUpperCase().replace(/-/g,"_")}`}async function Zn(e,t){let n=T.join(e,"backends","gateway");te.existsSync(n)&&await te.promises.copyFile(T.join(t,"wrangler.gateway.toml"),T.join(n,"wrangler.toml"))}async function eo(e,t){let n=T.join(e,".env.example"),o;try{o=await te.promises.readFile(n,"utf8")}catch(i){if(i.code==="ENOENT")return;throw i}if(o.includes("# Deployment Targets"))return;let s=["","# Deployment Targets",...Object.entries(t).map(([i,a])=>`${Is(i)}="${a}"`)].join(`
6
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(`
7
+ `)}async function to(e,t){if(t==="none")return;let n=Cs();t==="vercel"?(await te.promises.copyFile(T.join(n,"vercel.json"),T.join(e,"vercel.json")),await Zn(e,n)):t==="railway"?await te.promises.copyFile(T.join(n,"railway.toml"),T.join(e,"railway.toml")):t==="cloudflare"?(await te.promises.copyFile(T.join(n,"wrangler.toml"),T.join(e,"wrangler.toml")),await Zn(e,n)):t==="selfhost"&&(await te.promises.copyFile(T.join(n,"docker-compose.yml"),T.join(e,"docker-compose.yml")),await te.promises.copyFile(T.join(n,"Dockerfile.web"),T.join(e,"Dockerfile.web")))}var xs={qstash:"foundation",bullmq:"foundation",upstash:"foundation",sqs:"foundation",meilisearch:"foundation",typesense:"foundation",algolia:"foundation",pgvector:"foundation","vercel-flags":"foundation",growthbook:"foundation",configcat:"foundation",turnstile:"wip",hcaptcha:"wip","aliyun-slide":"wip",invite:"foundation"};function Rs(e){return e?xs[e]??"stable":"stable"}function et(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function Te(e){switch(e){case"stable":return"Production-ready.";case"foundation":return"Foundation status \u2014 core contracts work, but production use still requires provider credentials, adapter wiring, or a verified integration contract.";case"wip":return"WIP \u2014 actively being built, should not be used in production.";case"deprecated":return"Deprecated \u2014 scheduled for removal, do not use."}}function It(e){let t=[];for(let{flag:n,provider:o}of e){if(!o||o==="none")continue;let r=Rs(o);r!=="stable"&&t.push({flag:n,provider:o,status:r})}return t}function _e(e,t){if(e===void 0)return t;let n=String(e).trim().toLowerCase();return n==="true"||n==="1"||n==="yes"||n==="on"?!0:n==="false"||n==="0"||n==="no"||n==="off"?!1:t}function no(e,t){let n=t==="cn";return{cronJobs:_e(e.cronJobs,!0),auditLog:_e(e.auditLog,!1),apiKeys:_e(e.apiKeys,!0),webhooks:_e(e.webhooks,!0),commandPalette:_e(e.commandPalette,!0),cookieConsent:_e(e.cookieConsent,!0),legalPages:_e(e.legalPages,!0),chinaCompliance:_e(e.chinaCompliance,n)}}async function ks(e,t,n,o){let r={};return t||(r.region=()=>q.select({message:"Target region?",options:[{value:"global",label:"Global",hint:"Stripe \xB7 Resend \xB7 R2 defaults"},{value:"cn",label:"China",hint:"WeChat Pay \xB7 Aliyun DM/OSS defaults"},{value:"hybrid",label:"Hybrid",hint:"global + CN dual track"}],initialValue:"global"})),n||(r.auth=()=>q.select({message:"Auth provider?",options:[{value:"clerk",label:"Clerk",hint:"managed, fastest setup"},{value:"betterauth",label:"Better Auth",hint:"self-hosted, modern (2FA / passkeys / RBAC)"},{value:"nextauth",label:"NextAuth (Auth.js v5)",hint:"self-hosted, mature, large ecosystem"},{value:"supabase",label:"Supabase Auth",hint:"managed auth with Supabase storage/realtime ecosystem"},{value:"none",label:"None"}],initialValue:"clerk"})),o||(r.aiMode=()=>q.select({message:"AI topology?",options:[{value:"gateway",label:"Multi-provider AI Gateway / router",hint:"recommended"},{value:"direct",label:"Direct SDK/provider adapters"},{value:"custom",label:"OpenAI-compatible endpoint"},{value:"none",label:"Skip AI"}],initialValue:"gateway"}),r.aiProviders=({results:s})=>{if(s.aiMode!=="direct")return Promise.resolve([]);let i=ln.map(a=>({value:a.id,label:`[${a.category}] ${a.name}`}));return q.multiselect({message:"Select direct AI provider adapters (expert path)",options:i,initialValues:["openai"],required:!1})},r.customAiName=({results:s})=>s.aiMode==="custom"?q.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),r.customAiBaseUrl=({results:s})=>s.aiMode==="custom"?q.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:i=>{if(!i?.length)return"Base URL is required."}}):Promise.resolve(void 0),r.customAiApiKeyEnv=({results:s})=>s.aiMode==="custom"?q.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0)),Object.keys(r).length===0?{}:await q.group(r,{onCancel:()=>{process.stdout.write(Ts.red(`\u2718 Cancelled
8
+ `)),process.exit(130)}})}async function oo(e,t){let n=!!e.region,o=!!e.auth,r=!!e.payment,s=!!e.ai,i=!!e.email,a=!!e.storage,c=!!e.monitoring,p=!!e.analytics,d=!!e.sms,u=e.i18n!==void 0,h=!!e.yes||!process.stdin.isTTY,g,E,S,m,_,H,M,he=Xn(e.socialLogin),le,ee,$,K,C,W,de;if(h){g=cn(e.region),E=nn(e.orm);{let Y=en(e.db),At=tn(e.dbHost,g,Y);S=At.engine,m=At.hostId}let X=r?e.payment:pn(g);_=gt(X),H=ft(X),M=on(e.auth);let Qe="gateway";if(s){let Y=e.ai?.trim().toLowerCase()??"";rn(Y)?Qe=Y:Qe="direct"}let ut=dn({mode:Qe,providerIds:s?sn(e.ai):void 0});le=ut.mode,ee=ut.routing,$=ut.providerIds,C=yt(e.deploy),W=an(e.docs,t),de=u?!!e.i18n:!0}else{let X=await ks(e,n,o,s);g=cn(n?e.region:X.region),E=nn(e.orm);{let At=en(e.db),Mn=tn(e.dbHost,g,At);S=Mn.engine,m=Mn.hostId}let Qe=r?e.payment:pn(g);_=gt(Qe),H=ft(Qe),M=on(o?e.auth:X.auth);let ut=X.aiMode==="custom"?{name:X.customAiName??"custom",baseURL:X.customAiBaseUrl??"",apiKeyEnvName:X.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,Y=dn({mode:s?e.ai?.trim().toLowerCase()==="none"?"none":"direct":X.aiMode??"gateway",providerIds:s?sn(e.ai):X.aiProviders,customEndpoint:ut});le=Y.mode,ee=Y.routing,$=Y.providerIds,Y.customEndpoint&&(K={name:Y.customEndpoint.name,baseURL:Y.customEndpoint.baseURL,apiKeyEnvName:Y.customEndpoint.apiKeyEnvName}),C=yt(e.deploy),W=an(e.docs,t),de=u?!!e.i18n:!0}let P=Hn(g),Ee=i?e.email:P.email,ze=Gn(a?e.storage:void 0,P.storage),Je=c?e.monitoring:P.monitoring,ve=p?e.analytics:P.analytics,v=d?e.sms:P.sms,R=e.queue??P.queue,w=e.search??P.search,I=e.cache??P.cache,Gt=e.notifications??P.notifications,Ht=e.webhooks??P.webhooks,kn=e.cms??P.cms,Wt=e.featureFlags??P.featureFlags,Xt=e.captcha??P.captcha,Nn=e.mcp??P.mcp,On=e.metering??P.metering,Ln=e.billingMode??P.billingMode,Un=e.idp??P.idp,zt=e.accessGate==="invite"?"invite":P.accessGate,Dn=Ct(C),be=no({cronJobs:e.cronJobs,auditLog:e.auditLog,apiKeys:e.apiKeys,commandPalette:e.commandPalette,cookieConsent:e.cookieConsent,legalPages:e.legalPages,chinaCompliance:e.chinaCompliance},g),ss=It([{flag:"queue",provider:R},{flag:"search",provider:w},{flag:"notifications",provider:Gt},{flag:"webhooks",provider:Ht},{flag:"feature-flags",provider:Wt},{flag:"captcha",provider:Xt},{flag:"access-gate",provider:zt}]),is={region:g,orm:E,database:S,databaseHost:m,payment:_,aiMode:le,aiRouting:ee,aiProviders:$,customAiEndpoint:K,deployTarget:C,deployTargets:Dn,docs:W,i18n:de,email:Ee,storage:ze,monitoring:Je,analytics:ve,sms:v,queue:R,search:w,cache:I,notifications:Gt,webhooks:Ht,cms:kn,featureFlags:Wt,captcha:Xt,mcp:Nn,metering:On,billingMode:Ln,idp:Un,accessGate:zt,cronJobs:be.cronJobs,auditLog:be.auditLog,apiKeys:be.apiKeys,commandPalette:be.commandPalette,cookieConsent:be.cookieConsent,legalPages:be.legalPages,chinaCompliance:be.chinaCompliance};return{region:g,orm:E,database:S,databaseHost:m,payment:_,paymentChoice:H,auth:M,socialLoginIds:he,aiMode:le,aiRouting:ee,aiProviders:$,customAiEndpoint:K,deployTarget:C,deployTargets:Dn,docs:W,i18n:de,email:Ee,storage:ze,monitoring:Je,analytics:ve,sms:v,queue:R,search:w,cache:I,notifications:Gt,webhooks:Ht,cms:kn,featureFlags:Wt,captcha:Xt,mcp:Nn,metering:On,billingMode:Ln,idp:Un,accessGate:zt,waveToggles:be,previewSelections:ss,config:is}}import{execFileSync as Kt}from"child_process";import Yt from"fs";import Xe from"path";import We from"picocolors";import Xc from"update-notifier";import tt from"picocolors";function Ns(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function ro(e){let t=Ns(),n=t?"\u2693":"-",o=t?"\u25B8":"->",r=e.packageManager??"pnpm",s=e.hasDatabase!==!1,i=e.targetDir==="."||e.targetDir==="./"||e.targetDir===".\\",a=i?".":e.targetDir.endsWith("/")?e.targetDir:`${e.targetDir}/`,c=t?tt.bold(`${n} Done in ${e.elapsedSec}s \xB7 ${a}`):`${n} Done in ${e.elapsedSec}s \xB7 ${a}`,p=h=>t?tt.dim(h):h,d=h=>t?tt.bold(h):h,u=["",` ${c}`,"",` ${d("Next:")}`];i||u.push(` ${o} cd ${e.targetDir}`),e.skippedInstall&&u.push(` ${o} ${r} install`),u.push(` ${o} fill .env.local ${p("\u2192 provider keys from .env.example")}`),s&&u.push(` ${o} ${r} infra:up ${p("\u2192 local Postgres (optional)")}`,` ${o} ${r} db:migrate ${p("\u2192 apply Prisma schema")}`),u.push(` ${o} ${r} dev ${p("\u2192 http://localhost:3000")}`,"",` ${p("More:")} ${p("nebutra doctor")} ${p("\xB7")} ${p("docs.nebutra.com")}`);let A=e.previewSelections??[];if(A.length>0){let h=t?tt.bold(tt.yellow("\u26A0 Preview / foundation providers:")):"!! Preview / foundation providers:";u.push("",` ${h}`);for(let g of A){let E=et(g.status),S=` ${o} ${g.flag}=${g.provider} ${E}`;u.push(t?tt.yellow(S):S)}u.push(` ${p(Te("foundation"))}`)}u.push(""),process.stdout.write(u.join(`
9
9
  `)+`
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";
10
+ `)}import nt from"fs";import B from"path";var so=[{id:"posthog",name:"PostHog",region:"both",envVars:["POSTHOG_KEY","POSTHOG_HOST","NEXT_PUBLIC_POSTHOG_KEY","NEXT_PUBLIC_POSTHOG_HOST"],docs:"https://posthog.com/docs",pkgs:["posthog-js","posthog-node"],providerFile:"apps/web/src/lib/analytics/posthog.client.ts"},{id:"plausible",name:"Plausible",region:"global",envVars:["NEXT_PUBLIC_PLAUSIBLE_DOMAIN","NEXT_PUBLIC_PLAUSIBLE_SRC"],docs:"https://plausible.io/docs",providerFile:"apps/web/src/components/analytics/PlausibleScript.tsx"},{id:"umami",name:"Umami",region:"both",envVars:["NEXT_PUBLIC_UMAMI_WEBSITE_ID","NEXT_PUBLIC_UMAMI_SRC"],docs:"https://umami.is/docs",providerFile:"apps/web/src/components/analytics/UmamiScript.tsx"},{id:"mixpanel",name:"Mixpanel",region:"global",envVars:["MIXPANEL_TOKEN","NEXT_PUBLIC_MIXPANEL_TOKEN"],docs:"https://docs.mixpanel.com",pkgs:["mixpanel-browser","mixpanel"],providerFile:"apps/web/src/lib/analytics/mixpanel.client.ts"},{id:"baidu",name:"\u767E\u5EA6\u7EDF\u8BA1 Baidu Tongji",region:"cn",envVars:["NEXT_PUBLIC_BAIDU_STATS_ID"],docs:"https://tongji.baidu.com",providerFile:"apps/web/src/components/analytics/BaiduStatsScript.tsx"},{id:"sensors",name:"\u795E\u7B56 Sensors Analytics",region:"cn",envVars:["NEXT_PUBLIC_SENSORS_SERVER_URL","NEXT_PUBLIC_SENSORS_APP_JS_URL"],docs:"https://manual.sensorsdata.cn",pkgs:["sa-sdk-javascript"],providerFile:"apps/web/src/lib/analytics/sensors.client.ts"},{id:"growingio",name:"GrowingIO",region:"cn",envVars:["NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID"],docs:"https://growingio.com/docs",providerFile:"apps/web/src/components/analytics/GrowingIoScript.tsx"},{id:"none",name:"None",region:"both",envVars:[],docs:""}],tl=so.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function io(e){return so.find(t=>t.id===e)}function Os(e){nt.mkdirSync(e,{recursive:!0})}function ne(e,t){Os(B.dirname(e)),nt.writeFileSync(e,t)}function ke(e,t){let n=B.join(e,".env.example");nt.existsSync(n)?nt.appendFileSync(n,`
11
+ `+t):nt.writeFileSync(n,t)}function Ls(e){let t=`"use client";
12
12
  /**
13
13
  * PostHog browser SDK \u2014 lazy-initialized on first access.
14
14
  */
@@ -91,12 +91,12 @@ export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
91
91
 
92
92
  return <>{children}</>;
93
93
  }
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
94
+ `;ne(B.join(e,"src","lib","analytics","posthog.client.ts"),t),ne(B.join(e,"src","lib","analytics","posthog.server.ts"),n),ne(B.join(e,"src","components","analytics","AnalyticsProvider.tsx"),o)}function Us(){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 Ls(e){ne($.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
99
+ `}function Ds(e){ne(B.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
100
100
  /**
101
101
  * Plausible script tag \u2014 lightweight, privacy-friendly analytics.
102
102
  */
@@ -116,10 +116,10 @@ export function PlausibleScript() {
116
116
  />
117
117
  );
118
118
  }
119
- `)}function Us(){return`# Plausible \u2014 privacy-friendly analytics
119
+ `)}function Ms(){return`# Plausible \u2014 privacy-friendly analytics
120
120
  NEXT_PUBLIC_PLAUSIBLE_DOMAIN=
121
121
  NEXT_PUBLIC_PLAUSIBLE_SRC=https://plausible.io/js/script.js
122
- `}function Ds(e){ne($.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
122
+ `}function Fs(e){ne(B.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
123
123
  /**
124
124
  * Umami analytics \u2014 self-hosted OR umami.is cloud.
125
125
  */
@@ -139,10 +139,10 @@ export function UmamiScript() {
139
139
  />
140
140
  );
141
141
  }
142
- `)}function Ms(){return`# Umami \u2014 self-hostable analytics
142
+ `)}function js(){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 Fs(e){let t=`"use client";
145
+ `}function Bs(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
- `;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
184
+ `;ne(B.join(e,"src","lib","analytics","mixpanel.client.ts"),t),ne(B.join(e,"src","lib","analytics","mixpanel.server.ts"),n)}function Vs(){return`# Mixpanel \u2014 product analytics
185
185
  MIXPANEL_TOKEN=
186
186
  NEXT_PUBLIC_MIXPANEL_TOKEN=
187
- `}function Bs(e){ne($.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
187
+ `}function $s(e){ne(B.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
188
188
  /**
189
189
  * \u767E\u5EA6\u7EDF\u8BA1 Baidu Tongji \u2014 hm.js \u57CB\u70B9\u811A\u672C.
190
190
  */
@@ -210,9 +210,9 @@ var _hmt = _hmt || [];
210
210
  />
211
211
  );
212
212
  }
213
- `)}function $s(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
213
+ `)}function Ks(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
214
214
  NEXT_PUBLIC_BAIDU_STATS_ID=
215
- `}function Vs(e){ne($.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
215
+ `}function Ys(e){ne(B.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
216
216
  /**
217
217
  * \u795E\u7B56\u5206\u6790 (Sensors Analytics) \u2014 sa-sdk-javascript \u5C01\u88C5.
218
218
  */
@@ -240,10 +240,10 @@ export function initSensors(): void {
240
240
  }
241
241
 
242
242
  export { sensors };
243
- `)}function Ks(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
243
+ `)}function qs(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
244
244
  NEXT_PUBLIC_SENSORS_SERVER_URL=
245
245
  NEXT_PUBLIC_SENSORS_APP_JS_URL=
246
- `}function Ys(e){ne($.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
246
+ `}function Gs(e){ne(B.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
247
247
  /**
248
248
  * GrowingIO CDP \u2014 inline snippet installer.
249
249
  */
@@ -268,21 +268,21 @@ gdp("send");
268
268
  />
269
269
  );
270
270
  }
271
- `)}function qs(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
271
+ `)}function Hs(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
272
272
  NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID=
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,`
273
+ `}async function ao(e,t,n="global"){let o=io(t);if(!o||o.id==="none")return;let r=B.join(e,"apps","web");if(!nt.existsSync(r))return;let s=o.id;try{switch(s){case"posthog":Ls(r),ke(e,Us());return;case"plausible":Ds(r),ke(e,Ms());return;case"umami":Fs(r),ke(e,js());return;case"mixpanel":Bs(r),ke(e,Vs());return;case"baidu":$s(r),ke(e,Ks());return;case"sensors":Ys(r),ke(e,qs());return;case"growingio":Gs(r),ke(e,Hs());return;default:return}}catch(i){throw console.error(`Failed to apply analytics selection "${t}":`,i),new Error(`Analytics scaffold for "${t}" failed \u2014 see stderr for details.`)}}var Ws=Fn("analytics");function Xs(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function co(e,t={}){Xs(t)||(async()=>{try{let n=await import("./dist-ZZCU5PKC.js");if(typeof n.createProductAnalyticsClient!="function")return;let o=n.createProductAnalyticsClient({posthog:{apiKey:process.env.POSTHOG_KEY??process.env.NEXT_PUBLIC_POSTHOG_KEY??process.env.NEBUTRA_POSTHOG_KEY??"",host:process.env.POSTHOG_HOST??process.env.NEXT_PUBLIC_POSTHOG_HOST??process.env.NEBUTRA_POSTHOG_HOST??Ws},onError:()=>{}});if(typeof o?.track!="function")return;let r=o.track("scaffold.completed",e);r&&typeof r.then=="function"&&await r.catch(()=>{})}catch{}})()}import G from"fs";import k from"path";function V(e){G.existsSync(e)&&G.rmSync(e,{recursive:!0,force:!0})}function xt(e,t){let n=k.join(e,".env.example");G.existsSync(n)?G.appendFileSync(n,`
274
+ `+t):G.writeFileSync(n,t)}function Rt(e,t){if(!G.existsSync(e))return;let n=G.readFileSync(e,"utf8"),o=n.replace(/export type AuthProviderId\s*=\s*(?:"[^"]+"\s*\|\s*)+"[^"]+";/,`export type AuthProviderId = "${t}";`);o!==n&&G.writeFileSync(e,o)}function zs(e,t){let n=k.join(e,"README.md");if(!G.existsSync(n)){G.writeFileSync(n,t);return}G.appendFileSync(n,`
275
+ `+t)}async function po(e,t){let n=k.join(e,"packages","iam","auth");if(!G.existsSync(n))return;if(t==="none"){V(n),zs(e,`
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")),_t(r,"clerk"),bt(e,`# Clerk auth
279
+ `);return}let o=k.join(n,"src","providers"),r=k.join(n,"src","types.ts");if(t==="clerk"){V(k.join(o,"better-auth.ts")),V(k.join(o,"nextauth.ts")),V(k.join(o,"supabase.ts")),Rt(r,"clerk"),xt(e,`# Clerk auth
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")),_t(r,"better-auth"),bt(e,`# Better Auth
282
+ `);return}if(t==="betterauth"){V(k.join(o,"clerk.ts")),V(k.join(o,"nextauth.ts")),V(k.join(o,"supabase.ts")),Rt(r,"better-auth"),xt(e,`# Better Auth
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")),_t(r,"nextauth"),bt(e,`# NextAuth (Auth.js v5)
285
+ `);return}if(t==="nextauth"){V(k.join(o,"clerk.ts")),V(k.join(o,"better-auth.ts")),V(k.join(o,"supabase.ts")),Rt(r,"nextauth"),xt(e,`# NextAuth (Auth.js v5)
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")),_t(r,"supabase"),bt(e,`# Supabase Auth
293
+ `);return}if(t==="supabase"){V(k.join(o,"clerk.ts")),V(k.join(o,"better-auth.ts")),V(k.join(o,"nextauth.ts")),Rt(r,"supabase"),xt(e,`# Supabase Auth
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 Ne from"fs";import ke from"path";function Xs(e,t){let n=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
301
+ `);return}}import Oe from"fs";import Ne from"path";function Js(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 zs(e){return`"use client";
426
+ `}function Qs(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 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(`
469
+ `}function lo(e){Oe.mkdirSync(e,{recursive:!0})}function Zs(e,t){let n=Ne.join(e,".env.example");Oe.existsSync(n)?Oe.appendFileSync(n,`
470
+ `+t):Oe.writeFileSync(n,t)}function ei(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,n=e.envVars.map(o=>`${o}=`).join(`
471
471
  `);return`${t}
472
472
  ${n}
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(`
473
+ `}async function uo(e,t,n){if(!t||t.length===0)return;let o=Ne.join(e,"apps","web");if(!Oe.existsSync(o))return;let r=new Set,s=[];for(let p of t){if(r.has(p))continue;r.add(p);let d=Wn(p);d&&s.push(d)}if(s.length===0)return;for(let p of s)Zs(e,ei(p));let i=Ne.join(o,"src","app","api","auth","callback");for(let p of s){let d=Ne.join(i,p.id);lo(d);let u=Ne.join(d,"route.ts");Oe.writeFileSync(u,Js(p,n))}let a=Ne.join(o,"src","components","auth");lo(a);let c=Ne.join(a,"SocialLoginButtons.tsx");Oe.writeFileSync(c,Qs(s))}import ot from"fs";import go from"path";var Tt=[{id:"upstash-redis",name:"Upstash Redis",region:"both",envVars:["UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN"],docs:"https://upstash.com/docs/redis",description:"Serverless Redis"},{id:"vercel-kv",name:"Vercel KV",region:"global",envVars:["KV_URL","KV_REST_API_URL","KV_REST_API_TOKEN","KV_REST_API_READ_ONLY_TOKEN"],docs:"https://vercel.com/docs/storage/vercel-kv",description:"Vercel native KV"},{id:"redis",name:"Redis (self-hosted)",region:"both",envVars:["REDIS_URL"],docs:"https://redis.io/docs/",description:"Self-hosted Redis"},{id:"dragonfly",name:"Dragonfly",region:"global",envVars:["DRAGONFLY_URL"],docs:"https://www.dragonflydb.io/docs",description:"Drop-in Redis replacement, faster"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip cache package"}];function mo(e){return Tt.find(t=>t.id===e)}var yl=Tt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import oe from"fs";import kt from"path";function re(e,t){let n=kt.join(e,".env.example");if(!oe.existsSync(n)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(oe.readFileSync(n,"utf-8").includes(r))return;let a=["","# =============================================",r,t.docs?`# Docs: ${t.docs}`:null,"# =============================================",...t.envVars.map(c=>`${c}=""`),""].filter(c=>c!==null).join(`
474
+ `);oe.appendFileSync(n,a)}function se(e,t,n){let o=kt.join(e,".env.example");if(!oe.existsSync(o))return;let r=oe.readFileSync(o,"utf-8"),s=`${t}="${n}"`,i=new RegExp(`^${t}=.*$`,"m");if(i.test(r)){oe.writeFileSync(o,r.replace(i,s));return}let a=r.endsWith(`
475
475
  `)?"":`
476
476
  `;oe.appendFileSync(o,`${a}${s}
477
- `)}var 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(`
477
+ `)}var ti=["design","iam","commerce","integrations","platform","ops","ai"];function Le(e,t){for(let o of ti){let r=kt.join(e,"packages",o,t);if(oe.existsSync(r))return r}let n=kt.join(e,"packages",t);return oe.existsSync(n)?n:null}function J(e,t){let n=Le(e,t);n&&oe.rmSync(n,{recursive:!0,force:!0})}function fo(e){return ot.existsSync(e)?ot.readFileSync(e,"utf-8"):null}function ni(e,t){let n=go.join(e,".env.example"),o=fo(n);if(o===null)return;let r=`# Cache: ${t.name}`;if(o.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
478
+ `);ot.appendFileSync(n,s)}function oi(e,t,n){let o=go.join(e,".env.example"),r=fo(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?ot.writeFileSync(o,r.replace(s,`${t}="${n}"`)):ot.appendFileSync(o,`${t}="${n}"
479
+ `)}async function yo(e,t,n){let o=Le(e,"cache");if(t==="none"){o&&ot.rmSync(o,{recursive:!0,force:!0});return}let r=mo(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${Tt.map(s=>s.id).join(", ")}`);o&&(ni(e,r),oi(e,"CACHE_PROVIDER",t))}var Nt=[{id:"turnstile",name:"Cloudflare Turnstile",region:"global",envVars:["NEXT_PUBLIC_TURNSTILE_SITE_KEY","TURNSTILE_SECRET_KEY"],docs:"https://developers.cloudflare.com/turnstile/",description:"Free, privacy-focused captcha alternative"},{id:"hcaptcha",name:"hCaptcha",region:"global",envVars:["NEXT_PUBLIC_HCAPTCHA_SITE_KEY","HCAPTCHA_SECRET_KEY"],docs:"https://docs.hcaptcha.com/",description:"Privacy-respecting captcha"},{id:"aliyun-slide",name:"\u963F\u91CC\u4E91\u9A8C\u8BC1\u7801 2.0",region:"cn",envVars:["ALIYUN_CAPTCHA_ACCESS_KEY_ID","ALIYUN_CAPTCHA_ACCESS_KEY_SECRET","ALIYUN_CAPTCHA_APP_KEY","NEXT_PUBLIC_ALIYUN_CAPTCHA_APP_KEY"],docs:"https://help.aliyun.com/product/28308.html",description:"\u963F\u91CC\u4E91\u667A\u80FD\u9A8C\u8BC1 (\u6ED1\u5757/\u65E0\u75D5)"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function So(e){return Nt.find(t=>t.id===e)}var Cl=Nt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function ho(e,t,n="global"){let o=So(t);if(!o)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${Nt.map(r=>r.id).join(", ")}`);if(o.id==="none"){J(e,"captcha");return}o.envVars.length>0&&re(e,{category:"Captcha",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"CAPTCHA_PROVIDER",o.id)}import Lt from"fs";import ri from"path";var Ot=[{id:"sanity",name:"Sanity",region:"global",envVars:["SANITY_PROJECT_ID","SANITY_DATASET","SANITY_API_TOKEN","SANITY_API_VERSION"],docs:"https://www.sanity.io/docs",description:"Structured content platform with Studio"},{id:"contentful",name:"Contentful",region:"global",envVars:["CONTENTFUL_SPACE_ID","CONTENTFUL_ACCESS_TOKEN","CONTENTFUL_PREVIEW_ACCESS_TOKEN"],docs:"https://www.contentful.com/developers/docs/",description:"Headless CMS"},{id:"strapi",name:"Strapi",region:"both",envVars:["STRAPI_URL","STRAPI_API_TOKEN"],docs:"https://docs.strapi.io",description:"Open-source self-hosted CMS"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Eo(e){return Ot.find(t=>t.id===e)}var kl=Ot.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function vo(e,t,n="global"){let o=Eo(t);if(!o)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${Ot.map(s=>s.id).join(", ")}`);let r=ri.join(e,"apps","studio");if(o.id==="none"){J(e,"sanity"),Lt.existsSync(r)&&Lt.rmSync(r,{recursive:!0,force:!0});return}o.id!=="sanity"&&(J(e,"sanity"),Lt.existsSync(r)&&Lt.rmSync(r,{recursive:!0,force:!0})),o.envVars.length>0&&re(e,{category:"CMS",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"CMS_PROVIDER",o.id)}import U from"fs";import N from"path";var si=N.join("apps","web"),mn=N.join("src","components","compliance"),St=N.join("src","app","[locale]");function ie(e){return N.join(e,si)}function ii(e){U.mkdirSync(e,{recursive:!0})}function Q(e,t){ii(N.dirname(e)),U.writeFileSync(e,t,"utf8")}function gn(e,t){let n=N.join(e,".env.example");if(U.existsSync(n)){if(U.readFileSync(n,"utf8").includes(t.split(`
480
480
  `)[0]??""))return;U.appendFileSync(n,`
481
481
  `+t+`
482
482
  `)}else U.writeFileSync(n,t+`
483
- `)}var ut=`> **TEMPLATE \u2014 NOT LEGAL ADVICE.** This document is a boilerplate scaffold only.
483
+ `)}var ht=`> **TEMPLATE \u2014 NOT LEGAL ADVICE.** This document is a boilerplate scaffold only.
484
484
  > Consult a qualified lawyer in every jurisdiction you operate in before publishing.
485
- > \u672C\u6587\u6863\u4E3A\u6A21\u677F\u811A\u624B\u67B6\uFF0C\u4E0D\u6784\u6210\u6CD5\u5F8B\u610F\u89C1\u3002\u53D1\u5E03\u524D\u8BF7\u54A8\u8BE2\u76F8\u5173\u53F8\u6CD5\u8F96\u533A\u7684\u5408\u683C\u5F8B\u5E08\u3002`,si=`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`,ai=`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
- `,ii=`export function IcpFooter() {
536
+ `,ci=`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
- `,ai=`export function PublicSecurityFooter() {
550
+ `,pi=`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
- `,ci=`"use client";
567
+ `,li=`"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
- `,pi=`interface AigcDisclaimerProps {
721
+ `,di=`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
- `,li=`---
741
+ `,ui=`---
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
- ${ut}
747
+ ${ht}
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
- `,di=`---
886
+ `,mi=`---
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
- ${ut}
892
+ ${ht}
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
- `,ui=`---
1005
+ `,gi=`---
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
- ${ut}
1011
+ ${ht}
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
- `,mi=`---
1087
+ `,fi=`---
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
- ${ut}
1093
+ ${ht}
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
- `,gi=`---
1152
+ `,yi=`---
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
- ${ut}
1158
+ ${ht}
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 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})
1194
+ `;async function Si(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=N.join(n,"src","components","compliance","Footer.tsx");Q(o,ai);let r=N.join(n,"src","components","compliance","README.md");Q(r,["# Compliance Components","",`Auto-generated by \`create-sailor\` for region: \`${t}\`.`,"","## Mounting the Footer","","```tsx",'import { Footer } from "@/components/compliance/Footer";','import { CookieBanner } from "@/components/compliance/CookieBanner";',"","export default function RootLayout({ children }) {"," return ("," <html>"," <body>"," {children}",` <Footer region="${t}" />`," <CookieBanner />"," </body>"," </html>"," );","}","```","","## Placeholders","","Policy MDX files contain `{{COMPANY_NAME}}`, `{{COMPANY_ADDRESS}}`,","`{{COMPANY_CONTACT_EMAIL}}`, `{{GOVERNING_JURISDICTION}}`, and","`{{AIGC_ALGORITHM_FILING_NUMBER}}`. These are filled by the `brand-apply` step.",""].join(`
1195
+ `))}async function hi(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=N.join(n,"src","components","compliance","CookieBanner.tsx");Q(o,li)}async function Ei(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=N.join(n,St,"privacy","page.mdx");Q(o,ui)}async function vi(e,t){let n=ie(e);if(!U.existsSync(n))return;let o=N.join(n,St,"terms","page.mdx");Q(o,mi)}async function bi(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,mn,"IcpFooter.tsx");Q(n,ci),gn(e,["# Chinese ICP filing (\u5DE5\u4FE1\u90E8 ICP \u5907\u6848) \u2014 required to legally host a","# public-facing site from mainland China. Apply at https://beian.miit.gov.cn/",'NEXT_PUBLIC_ICP_BEIAN="" # \u5982 \u82CFICP\u59072024XXXXXX\u53F7'].join(`
1196
+ `))}async function _i(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,mn,"PublicSecurityFooter.tsx");Q(n,pi),gn(e,["# Chinese Public Security Bureau filing (\u516C\u5B89\u8054\u7F51\u5907\u6848)","# Required in addition to ICP. Apply at http://www.beian.gov.cn/",'NEXT_PUBLIC_PSB_BEIAN="" # \u5982 \u82CF\u516C\u7F51\u5B89\u5907 32011402XXXXXX\u53F7','NEXT_PUBLIC_PSB_CODE="" # 14-digit record code'].join(`
1197
+ `))}async function Pi(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,mn,"AigcDisclaimer.tsx");Q(n,di),gn(e,["# Generative AI algorithm filing (\u7B97\u6CD5\u5907\u6848\u53F7) \u2014 required by","# \u7F51\u4FE1\u529E\u300A\u751F\u6210\u5F0F\u4EBA\u5DE5\u667A\u80FD\u670D\u52A1\u7BA1\u7406\u6682\u884C\u529E\u6CD5\u300Bfor services offered in China.",'NEXT_PUBLIC_AIGC_FILING_NUMBER="" # e.g. \u7F51\u4FE1\u7B97\u5907XXXXXXXX\u53F7'].join(`
1198
+ `))}async function wi(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,St,"aigc-disclosure","page.mdx");Q(n,gi)}async function Ai(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,St,"cross-border-data","page.mdx");Q(n,fi)}async function Ci(e){let t=ie(e);if(!U.existsSync(t))return;let n=N.join(t,St,"pii-collection","page.mdx");Q(n,yi)}async function bo(e,t){try{await Si(e,t),await hi(e,t),await Ei(e,t),await vi(e,t),(t==="cn"||t==="hybrid")&&(await bi(e),await _i(e),await Pi(e),await wi(e),await Ai(e),await Ci(e))}catch(n){throw console.error("applyComplianceTemplates failed:",n),new Error(`Failed to apply compliance templates for region "${t}". Check that ${e} is writable.`)}}import Ii from"fs";import xi from"path";async function _o(e,t){let n=xi.join(e,"nebutra.config.json");Ii.writeFileSync(n,JSON.stringify(t,null,2)+`
1199
+ `)}import x from"fs";import Ue from"path";function Ri(e){x.existsSync(e)&&x.rmSync(e,{recursive:!0,force:!0})}function Po(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function Ti(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function wo(e){let t=e.replace(/^\s*extensions\s*=\s*\[[^\]]*\]\s*\n/gm,"");return t=t.replace(/previewFeatures\s*=\s*\[\s*"postgresqlExtensions"\s*\]\s*\n/g,""),t}function ki(e,t){let n=Ue.join(e,".env.example");x.existsSync(n)?x.appendFileSync(n,`
1200
+ `+t):x.writeFileSync(n,t)}async function Ao(e,t,n){let o=Ue.join(e,"packages","platform","db");if(t==="none"){Ri(o);return}let r=Ue.join(o,"prisma","schema.prisma"),s;if(t==="postgresql"?s=`postgresql://postgres:postgres@localhost:5432/${n}`:t==="mysql"?s=`mysql://root:root@localhost:3306/${n}`:s="file:./dev.db",ki(e,`# Database (${t})
1201
1201
  DATABASE_URL="${s}"
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}
1202
+ `),!x.existsSync(r))return;let i=x.readFileSync(r,"utf8"),a=i;t==="mysql"?(a=Po(a,"mysql"),a=wo(a)):t==="sqlite"&&(a=Po(a,"sqlite"),a=Ti(a),a=wo(a)),a!==i&&x.writeFileSync(r,a)}function Ni(e){let t=Ue.join(e,".env.example");return x.existsSync(t)?x.readFileSync(t,"utf8"):""}function Oi(e,t,n,o){let r=Ue.join(e,".env.example"),s=Ni(e),i=o?`# ${o}
1203
1203
  ${t}="${n}"
1204
1204
  `:`${t}="${n}"
1205
- `,a=new RegExp(`^\\s*${t}\\s*=.*$`,"m");if(a.test(s)){R.writeFileSync(r,s.replace(a,`${t}="${n}"`));return}s?R.appendFileSync(r,`
1206
- ${i}`):R.writeFileSync(r,i)}function 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(`
1205
+ `,a=new RegExp(`^\\s*${t}\\s*=.*$`,"m");if(a.test(s)){x.writeFileSync(r,s.replace(a,`${t}="${n}"`));return}s?x.appendFileSync(r,`
1206
+ ${i}`):x.writeFileSync(r,i)}function Li(e,t){let n=Ue.join(e,"packages","platform","db","prisma","schema.prisma");if(!x.existsSync(n))return;let o=x.readFileSync(n,"utf8"),r=/(datasource\s+db\s*\{[^}]*?)(\n})/;if(!o.match(r))return;let i=t.filter(p=>!o.includes(p.trim()));if(i.length===0)return;let a=i.map(p=>` ${p}`).join(`
1207
1207
  `),c=o.replace(r,`$1
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(`
1208
+ ${a}$2`);x.writeFileSync(n,c)}function Ui(e){let t=Ue.join(e,"packages","platform","db","prisma","schema.prisma");if(!x.existsSync(t))return;let n=x.readFileSync(t,"utf8");if(/directUrl\s*=\s*env\(/.test(n))return;let o=/(datasource\s+db\s*\{[\s\S]*?url\s*=\s*env\(\s*"DATABASE_URL"\s*\)[^\n]*\n)/;o.test(n)&&x.writeFileSync(t,n.replace(o,`$1 directUrl = env("DIRECT_URL")
1209
+ `))}async function Co(e,t,n){if(!(t.id==="none"||t.id==="local")){for(let o of t.envVars){let r=o.placeholder.replace(/\$PROJECT/g,n);Oi(e,o.name,r,o.comment)}t.prismaDatasourceExtras&&t.prismaDatasourceExtras.length>0&&Li(e,t.prismaDatasourceExtras),t.keepDirectUrl&&Ui(e)}}import Pe from"fs";import De from"path";import{fileURLToPath as Di}from"url";var Mi=Di(import.meta.url),Io=De.dirname(Mi),Fi=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,xo=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function ji(e){let t=[De.join(Io,"..","templates","docs",e),De.join(Io,"..","..","templates","docs",e)];for(let n of t)if(Pe.existsSync(n))return n;return t[0]}async function Ro(e,t){if(t.framework==="none")return;if(!xo.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${xo.join(", ")}, none.`);let n=ji(t.framework),o=De.join(e,"apps","docs");if(!Pe.existsSync(n))throw new Error(`Docs template not found: ${n}`);To(n,o),ko(o,{"{PRODUCT_NAME}":t.projectName})}function To(e,t){Pe.mkdirSync(t,{recursive:!0});for(let n of Pe.readdirSync(e,{withFileTypes:!0})){let o=De.join(e,n.name),r=De.join(t,n.name);n.isDirectory()?To(o,r):Pe.copyFileSync(o,r)}}function ko(e,t){for(let n of Pe.readdirSync(e,{withFileTypes:!0})){let o=De.join(e,n.name);if(n.isDirectory())ko(o,t);else if(Fi.test(n.name)){let r=Pe.readFileSync(o,"utf-8");for(let[s,i]of Object.entries(t))r=r.split(s).join(i);Pe.writeFileSync(o,r)}}}import Fe from"fs";import Me from"path";var rt=[{id:"resend",name:"Resend",region:"global",envVars:["RESEND_API_KEY","RESEND_FROM"],docs:"https://resend.com/docs",pkg:"resend",pkgVersion:"^4.0.1"},{id:"postmark",name:"Postmark",region:"global",envVars:["POSTMARK_API_KEY","POSTMARK_FROM"],docs:"https://postmarkapp.com/developer",pkg:"postmark",pkgVersion:"^4.0.5"},{id:"ses",name:"AWS SES",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_SES_REGION","SES_FROM"],docs:"https://docs.aws.amazon.com/ses",pkg:"@aws-sdk/client-sesv2",pkgVersion:"^3.658.0"},{id:"aliyun-dm",name:"\u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001",region:"cn",envVars:["ALIYUN_DM_ACCESS_KEY","ALIYUN_DM_ACCESS_SECRET","ALIYUN_DM_ACCOUNT_NAME","ALIYUN_DM_FROM_ALIAS"],docs:"https://help.aliyun.com/product/29412.html",pkg:"@alicloud/dm20151123",pkgVersion:"^3.0.0"},{id:"tencent-ses",name:"\u817E\u8BAF\u4E91 SES",region:"cn",envVars:["TENCENT_SECRET_ID","TENCENT_SECRET_KEY","TENCENT_SES_FROM_EMAIL"],docs:"https://cloud.tencent.com/document/product/1288",pkg:"tencentcloud-sdk-nodejs-ses",pkgVersion:"^4.0.900"},{id:"netease",name:"\u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1",region:"cn",envVars:["NETEASE_USER","NETEASE_PASS","NETEASE_FROM"],docs:"https://qiye.163.com/help",pkg:"nodemailer",pkgVersion:"^6.9.15"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function No(e){return rt.find(t=>t.id===e)}var Ql=rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var je="@nebutra/email";function fn(e,t){Fe.mkdirSync(Me.dirname(e),{recursive:!0}),Fe.writeFileSync(e,t)}function Bi(e,t){let n=Me.join(e,".env.example");Fe.existsSync(n)?Fe.appendFileSync(n,`
1210
+ `+t):Fe.writeFileSync(n,t)}function Vi(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
1211
1211
  `);return`${t}
1212
1212
  ${n}
1213
- `}var Bi=`/**
1213
+ `}var $i=`/**
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 $i(){return`/**
1234
- * @${Fe.slice(1)} \u2014 Resend transactional email wrapper.
1233
+ `;function Ki(){return`/**
1234
+ * @${je.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 Vi(){return`/**
1273
- * @${Fe.slice(1)} \u2014 Postmark transactional email wrapper.
1272
+ `}function Yi(){return`/**
1273
+ * @${je.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 Ki(){return`/**
1311
- * @${Fe.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
1310
+ `}function qi(){return`/**
1311
+ * @${je.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 Yi(){return`/**
1367
- * @${Fe.slice(1)} \u2014 \u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001 (Aliyun DirectMail) wrapper.
1366
+ `}function Gi(){return`/**
1367
+ * @${je.slice(1)} \u2014 \u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001 (Aliyun DirectMail) wrapper.
1368
1368
  *
1369
1369
  * Docs: https://help.aliyun.com/product/29412.html
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 qi(){return`/**
1417
- * @${Fe.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
1416
+ `}function Hi(){return`/**
1417
+ * @${je.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 Gi(){return`/**
1465
- * @${Fe.slice(1)} \u2014 \u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1 via SMTP (nodemailer).
1464
+ `}function Wi(){return`/**
1465
+ * @${je.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 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(`
1502
+ `}function Xi(e){switch(e){case"resend":return Ki();case"postmark":return Yi();case"ses":return qi();case"aliyun-dm":return Gi();case"tencent-ses":return Hi();case"netease":return Wi();case"none":return`export {};
1503
+ `}}function zi(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),e.id==="aliyun-dm"&&(t["@alicloud/openapi-client"]="^0.4.12");let n={name:je,version:"0.1.0",private:!0,description:`Transactional email via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
1504
+ `}async function Oo(e,t,n){if(t==="none")return;let o=No(t);if(!o)throw new Error(`Unknown email provider "${t}". Valid ids: ${rt.map(i=>i.id).join(", ")}`);let r=Me.join(e,"packages","email"),s=Me.join(r,"src");Fe.existsSync(s)&&Fe.rmSync(s,{recursive:!0,force:!0}),fn(Me.join(r,"package.json"),zi(o)),fn(Me.join(s,"types.ts"),$i),fn(Me.join(s,"index.ts"),Xi(o.id)),Bi(e,Vi(o))}import ue from"fs";import Lo from"path";function Ji(e,t){return new RegExp(`^\\s*${t}\\s*=`,"m").test(e)}function Uo(e){return e.endsWith(`
1505
1505
  `)?e:`${e}
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
1506
+ `}async function Do(e,t){let n=Lo.join(e,".env"),o=Lo.join(e,".env.local"),r=ue.existsSync(n)?ue.readFileSync(n,"utf8"):"",s=ue.existsSync(o)?ue.readFileSync(o,"utf8"):"",i=`${r}
1507
+ ${s}`,a=[{name:"DATABASE_URL",value:String(t.databaseUrl)},{name:"NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY",value:String(t.clerkPublishable)},{name:"CLERK_SECRET_KEY",value:String(t.clerkSecret)},{name:"NEXT_PUBLIC_SITE_URL",value:"http://localhost:3000"}].filter(p=>!Ji(i,p.name)).map(p=>`${p.name}="${p.value}"`);if(a.length===0)return;let c=`# Automatically injected by create-sailor
1508
1508
  ${a.join(`
1509
1509
  `)}
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"}
1510
+ `;try{let p=ue.readFileSync(o,"utf8"),d=Uo(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,`${Uo(p)}
1512
+ ${c}`)}}}import Fo from"crypto";import Et from"fs";import Mo from"path";function Be(e){return Fo.randomBytes(e).toString("base64").replace(/=+$/,"")}function Qi(e){return Fo.randomBytes(e).toString("hex")}function Zi(){return{AUTH_SECRET:Be(32),NEXTAUTH_SECRET:Be(32),BETTER_AUTH_SECRET:Be(32),JWT_SECRET:Be(32),WEBHOOK_SECRET:Qi(16),ENCRYPTION_KEY:Be(32),API_SECRET_KEY:Be(32),SESSION_SECRET:Be(32)}}function ea(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function ta(e,t,n){let o=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=ea(n);return e.replace(o,`${t}="${r}"`)}async function jo(e){let t=Mo.join(e,".env.example"),n=Mo.join(e,".env.local");if(!Et.existsSync(t))return null;try{let o=Et.readFileSync(t,"utf8"),r=Zi(),i=Et.existsSync(n)?Et.readFileSync(n,"utf8"):o;for(let a of Object.keys(r))i=ta(i,a,r[a]);return Et.writeFileSync(n,i),r}catch(o){let r=o instanceof Error?o.message:String(o);throw console.error(`[create-sailor] Failed to generate env secrets: ${r}`),new Error(`Unable to write .env.local: ${r}`)}}var Ut=[{id:"vercel-flags",name:"Vercel Flags SDK",region:"global",envVars:["FLAGS_SECRET"],docs:"https://vercel.com/docs/workflow-collaboration/feature-flags",description:"Native Vercel feature flags"},{id:"growthbook",name:"GrowthBook",region:"both",envVars:["GROWTHBOOK_API_HOST","GROWTHBOOK_CLIENT_KEY","GROWTHBOOK_DECRYPTION_KEY"],docs:"https://docs.growthbook.io",description:"Open-source A/B testing + flags"},{id:"configcat",name:"ConfigCat",region:"global",envVars:["CONFIGCAT_SDK_KEY"],docs:"https://configcat.com/docs/",description:"Feature flag & config management"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Bo(e){return Ut.find(t=>t.id===e)}var dd=Ut.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Vo(e,t,n="global"){let o=Bo(t);if(!o)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${Ut.map(r=>r.id).join(", ")}`);if(o.id==="none"){J(e,"feature-flags");return}o.envVars.length>0&&re(e,{category:"Feature Flags",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"FEATURE_FLAGS_PROVIDER",o.id)}import{execFileSync as qo}from"child_process";import O from"fs";import na from"os";import ae from"path";import oa from"ignore";var ra={mirror:{repo:process.env.SAILOR_TEMPLATE_REPO||"Nebutra/Sailor-Template",ref:process.env.SAILOR_TEMPLATE_REF||"main",applyIgnore:!1,allowMutableFallback:process.env.SAILOR_TEMPLATE_ALLOW_MUTABLE_FALLBACK==="1"},main:{repo:"Nebutra/Nebutra-Sailor",ref:"main",applyIgnore:!0,allowMutableFallback:process.env.SAILOR_TEMPLATE_ALLOW_MUTABLE_FALLBACK==="1"}};function sa(){let e=process.env.SAILOR_TEMPLATE_LOCAL_DIR;if(!(!e||e.trim().length===0))return ae.resolve(e.trim())}var ia=new Set(["node_modules",".git","dist",".next",".turbo"]);function aa(e,t){if(!O.statSync(e).isDirectory())throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR is not a directory: ${e}`);O.cpSync(e,t,{recursive:!0,dereference:!0,filter:o=>{let r=ae.basename(o);return!ia.has(r)}})}function ca(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function pa(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function Go(e){return/^[0-9a-f]{7,40}$/i.test(e)}function la(e,t){let n=`https://github.com/${e}.git`,o=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of o)try{let s=qo("git",["ls-remote",n,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!s)continue;let[i]=s.split(/\s+/);if(Go(i))return i}catch{}return null}async function da(e,t){if(Go(t))return t;let n=await fetch(`https://api.github.com/repos/${e}/commits/${encodeURIComponent(t)}`,{headers:{Accept:"application/vnd.github+json","User-Agent":"create-sailor"}});if(!n.ok){let r=la(e,t);if(r)return r;throw new Error(`Failed to resolve ${e}@${t} (GitHub API ${n.status})`)}let o=await n.json();if(typeof o.sha!="string"||o.sha.length===0)throw new Error(`GitHub API did not return a commit SHA for ${e}@${t}`);return o.sha}function Ho(e,t,n){let o=O.readdirSync(t,{withFileTypes:!0});for(let r of o){if(r.name==="node_modules"||r.name===".git")continue;let s=ae.join(t,r.name),i=ae.relative(e,s).split(ae.sep).join("/");r.isDirectory()?(n.push(i+"/"),Ho(e,s,n)):n.push(i)}}function $o(e){let t=ae.join(e,".templateignore");if(!O.existsSync(t))return;let n=O.readFileSync(t,"utf8"),o=oa().add(n),r=[];Ho(e,e,r);let s=r.map(c=>c.endsWith("/")?c.slice(0,-1):c),i=new Set(o.filter(s)),a=s.filter(c=>!i.has(c)).sort((c,p)=>p.split("/").length-c.split("/").length);for(let c of a){let p=ae.join(e,c);try{O.existsSync(p)&&O.rmSync(p,{recursive:!0,force:!0})}catch{}}try{O.existsSync(t)&&O.rmSync(t,{force:!0})}catch{}}async function Ko(e,t){let n=await fetch(e,{headers:{Accept:"application/octet-stream","User-Agent":"create-sailor"}});if(!n.ok)throw new Error(`Failed to download archive (${n.status})`);let o=Buffer.from(await n.arrayBuffer());if(o.byteLength<1024)throw new Error(`Downloaded archive is unexpectedly small (${o.byteLength} bytes)`);O.writeFileSync(t,o);let r=O.statSync(t);if(r.size!==o.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${o.byteLength})`);return r.size}function Yo(e,t){qo("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function yn(e){try{let t=O.readdirSync(e);for(let n of t)O.rmSync(ae.join(e,n),{recursive:!0,force:!0})}catch{}}async function ua(e,t){let n=O.mkdtempSync(ae.join(na.tmpdir(),"create-sailor-")),o=ae.join(n,"template.tar.gz");try{let r=await da(e.repo,e.ref);await Ko(pa(e.repo,r),o),Yo(o,t)}catch(r){if(!e.allowMutableFallback)throw r;yn(t),await Ko(ca(e.repo,e.ref),o),Yo(o,t)}finally{O.rmSync(n,{recursive:!0,force:!0})}}async function Wo(e){O.mkdirSync(e,{recursive:!0});let t=sa();if(t){if(!O.existsSync(t))throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR does not exist: ${t}`);yn(e),aa(t,e);try{$o(e)}catch(s){throw new Error(`Local template copied, but .templateignore processing failed: ${s instanceof Error?s.message:String(s)}`)}return}let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],r;for(let s of o){let i=ra[s];try{if(await ua(i,e),i.applyIgnore)try{$o(e)}catch(a){throw new Error(`Template cloned, but .templateignore processing failed: ${a instanceof Error?a.message:String(a)}`)}return}catch(a){r=a instanceof Error?a:new Error(String(a)),yn(e)}}throw new Error(`Failed to download the template from any source. Last error: ${r?.message??"unknown"}
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 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
1515
+ You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import Dt from"fs";import Sn from"path";var ma="node scripts/governance/lint-no-raw-inputs.mjs",ga="node scripts/governance/lint-repository-seam.mjs",fa="node scripts/governance/lint-brand-literals.mjs",ya="node scripts/governance/lint-microcopy.mjs",Sa=/\bnode\s+scripts\/(governance\/)?lint-[\w-]+\.mjs/g,ha=/\bnode\s+scripts\/lint-[\w-]+\.mjs/,Ea={scanRoots:["apps"],primitivesImport:"@nebutra/ui/primitives",whitelist:["/storybook/src/stories/","/design-docs/src/components/previews/","/sailor-docs/src/components/previews/","\\.test\\.tsx?$","/__tests__/"]},va={coreDomains:["^packages/.*/(billing|license|metering|auth|audit|permissions|identity|tenant)/","^backends/gateway/src/routes/(billing|ai|admin|legal|integrations|webhooks)/","^apps/web/src/app/api/"],seamPaths:["^packages/platform/repositories/","^packages/platform/db/"],dbAccessors:["getTenantDb","getSystemDb"],allowlist:["apps/web/src/app/api/invitations/[invitationId]/accept/route.ts","apps/web/src/app/api/onboarding/invite-members/route.ts","apps/web/src/app/api/startup-os/projects/[projectId]/runs/[runId]/execute/route.ts","apps/web/src/app/api/cofounder/room/[profileId]/form-team/route.ts","apps/web/src/app/api/provider-keys/route.ts","backends/gateway/src/routes/admin/index.ts","backends/gateway/src/routes/ai/api-keys.ts","backends/gateway/src/routes/ai/usage.ts","backends/gateway/src/routes/billing/index.ts","backends/gateway/src/routes/integrations/index.ts","backends/gateway/src/routes/legal/consent.ts","backends/gateway/src/routes/webhooks/clerk.ts","backends/gateway/src/routes/webhooks/stripe.ts","packages/commerce/license/src/issue-license.ts","packages/commerce/license/src/validate-license.ts","packages/commerce/billing/src/credits/service.ts","packages/commerce/billing/src/usage/ledger.ts","packages/iam/audit/src/index.ts","packages/iam/auth/src/plugins/passkey-plugin.ts"]},ba={scanRoots:["apps/web/src"],excludePaths:["/api/","\\.test\\.tsx?$","/__tests__/","/storybook/src/stories/","/design-docs/","/sailor-docs/"],bannedPatterns:[],allowlist:[]},Xo={governedPaths:["apps","packages/commerce","packages/integrations/email"],allowExpressions:["Nebutra","\u4E91\u6BD3\u667A\u80FD","\u4E91\u6BD3","^https?://([a-z0-9-]+\\.)?nebutra\\.com(?:/|$)","^https?://([a-z0-9-]+\\.)?nebutra\\.ai(?:/|$)","#0033FE","#0BF1C3"],knownExemptPatterns:["\\.stories\\.tsx?$","/__tests__/","\\.test\\.tsx?$","/previews/","^packages/design/brand/","^packages/design/tokens/","^packages/design/design-tokens/"],allowlist:[]},_a=["apps/design-docs/mdx-components.tsx","apps/design-docs/next.config.ts","apps/design-docs/src/__registry__/index.tsx","apps/design-docs/src/app/[lang]/docs/[[...slug]]/page.tsx","apps/design-docs/src/app/[lang]/docs/layout.tsx","apps/design-docs/src/app/[lang]/layout.tsx","apps/design-docs/src/app/[lang]/registry/[name]/page.tsx","apps/design-docs/src/app/[lang]/registry/page.tsx","apps/design-docs/src/app/og/docs/[...slug]/route.tsx","apps/design-docs/src/components/brand-overview-visuals.tsx","apps/design-docs/src/components/color-usage.tsx","apps/design-docs/src/components/component-preview.tsx","apps/design-docs/src/components/gradient-demos.tsx","apps/design-docs/src/components/introduction-hero.tsx","apps/design-docs/src/components/motion-demos.tsx","apps/design-docs/src/components/pattern-demos.tsx","apps/design-docs/src/components/registry/registry-card.tsx","apps/design-docs/src/lib/github.ts","apps/design-docs/src/lib/registry-strings.ts","apps/design-docs/src/lib/registry.ts","apps/idp/src/app/layout.tsx","apps/idp/src/app/oauth/authorize/page.tsx","apps/idp/src/app/page.tsx","apps/idp/src/lib/oidc.ts","apps/landing/src/app/[lang]/layout.tsx","apps/landing/src/app/api/blog/comments/route.ts","apps/landing/src/app/api/blog/reactions/route.ts","apps/landing/src/app/api/og/route.ts","apps/landing/src/app/apple-icon.tsx","apps/landing/src/components/auth/google-one-tap.tsx","apps/landing/src/components/cookie-consent-banner.tsx","apps/landing/src/components/marketing/ProductHuntSection.tsx","apps/landing/src/components/marketing/TestimonialsSection.tsx","apps/landing/src/i18n/request.ts","apps/landing/src/lib/analytics/emit.ts","apps/landing/src/lib/blog-fallback.ts","apps/landing/src/lib/constants/playbook-data.ts","apps/landing/src/lib/constants/resources-data.ts","apps/landing/src/lib/constants/solutions-data.ts","apps/landing/src/lib/docs-links.ts","apps/landing/src/lib/env.ts","apps/landing/src/lib/landing-content.ts","apps/landing/src/lib/seo/metadata.ts","apps/landing/src/lib/seo/site-routes.ts","apps/landing/src/lib/status-checks.ts","apps/landing/src/proxy.ts","apps/mail-preview/scripts/export.ts","apps/mail-preview/scripts/render-react-templates.ts","apps/mail-preview/src/app/api/send-test/route.ts","apps/mail-preview/src/app/layout.tsx","apps/mail-preview/src/lib/fixtures.ts","apps/web/next.config.ts","apps/web/src/app/(app)/checkout-return/page.tsx","apps/web/src/app/(app)/choose-plan/page.tsx","apps/web/src/app/(app)/settings/api-keys/page.tsx","apps/web/src/app/(app)/settings/notifications/page.tsx","apps/web/src/app/(app)/settings/provider-keys/page.tsx","apps/web/src/app/(auth)/desktop-auth/complete/page.tsx","apps/web/src/app/(public)/page.tsx","apps/web/src/app/[locale]/welcome/page.tsx","apps/web/src/app/api/account/email-change/route.ts","apps/web/src/app/api/admin/access-invites/route.ts","apps/web/src/app/api/blog/comments/route.ts","apps/web/src/app/api/blog/reactions/route.ts","apps/web/src/app/api/me/public/route.ts","apps/web/src/app/api/organizations/[orgId]/members/route.ts","apps/web/src/app/global-error.tsx","apps/web/src/components/ErrorBoundary.tsx","apps/web/src/components/api-keys/create-api-key-dialog.tsx","apps/web/src/components/appearance/store.ts","apps/web/src/components/auth/auth-banner.tsx","apps/web/src/components/auth/desktop-auth-complete-handoff.tsx","apps/web/src/components/auth/sign-up-form.tsx","apps/web/src/components/billing/billing-self-service.tsx","apps/web/src/components/navigation/public-page-chrome.tsx","apps/web/src/components/notifications/inbox-bell.tsx","apps/web/src/components/notifications/notification-inbox-preview.tsx","apps/web/src/components/notifications/notification-preference-matrix.tsx","apps/web/src/components/notifications/notification-runtime-banner.tsx","apps/web/src/components/settings/security/security-capabilities.ts","apps/web/src/components/settings/security/security-settings-client.tsx","apps/web/src/components/theme-playground/design-md-import.tsx","apps/web/src/components/theme-playground/theme-playground-workbench.tsx","apps/web/src/components/theme-playground/theme-token-data.ts","apps/web/src/lib/api.ts","apps/web/src/lib/api/client.ts","apps/web/src/lib/env.ts","apps/web/src/lib/integrations/catalog.tsx","apps/web/src/lib/permissions.ts","apps/web/src/lib/public-url-defaults.ts","apps/web/src/lib/session-hint.ts","apps/web/src/lib/startup-os/company-context/generate.ts","apps/web/src/lib/startup-os/company-context/projection.ts","apps/web/src/lib/startup-os/conversation.ts","apps/web/src/lib/startup-os/execution.ts","apps/web/src/lib/startup-os/files.ts","apps/web/src/proxy.ts","packages/commerce/billing/src/index.ts","packages/commerce/contracts/src/identity.ts","packages/commerce/legal/src/components/CookieBanner.tsx","packages/commerce/legal/src/documents/config.ts","packages/commerce/legal/src/index.ts","packages/commerce/marketing/src/components/ProductHuntBadge.tsx","packages/commerce/marketing/src/config/index.ts","packages/commerce/marketing/src/index.ts","packages/integrations/email/src/index.ts","packages/integrations/email/src/templates/_layout.ts","packages/integrations/email/src/templates/invitation.tsx"];function Pa(e,t){let n=(e??"").replace(Sa,"").split("&&").map(r=>r.trim()).filter(Boolean).join(" && ");return[n.length>0?n:"biome check .",...t].join(" && ")}function wa(e){let t=new RegExp(Xo.allowExpressions.join("|"));return _a.filter(n=>{try{return t.test(Dt.readFileSync(Sn.join(e,n),"utf8"))}catch{return!1}})}async function zo(e,t){let n=t.database!=="none",o=[ma];n&&o.push(ga),o.push(fa),o.push(ya);let r={...Xo,allowlist:wa(e)},s={rawInputs:Ea,brandLiterals:r,microcopyRules:ba};n&&(s.repositorySeam=va);let i=Sn.join(e,"governance.config.json");Dt.writeFileSync(i,JSON.stringify(s,null,2)+`
1516
+ `);let a=Sn.join(e,"package.json"),c;try{c=Dt.readFileSync(a,"utf8")}catch(p){if(p.code!=="ENOENT")throw p}if(c!==void 0){let p=JSON.parse(c);p.scripts=p.scripts??{};for(let[d,u]of Object.entries(p.scripts))d!=="lint"&&typeof u=="string"&&ha.test(u)&&delete p.scripts[d];p.scripts.lint=Pa(p.scripts.lint,o),Dt.writeFileSync(a,JSON.stringify(p,null,2)+`
1517
+ `)}return{lints:o,configWritten:!0}}import Z from"fs";import ce from"path";import{fileURLToPath as Aa}from"url";var Ca=Aa(import.meta.url),Jo=ce.dirname(Ca),Qo="scaffold-meta.json",Zo=".nebutra";function Ia(e){if(e)return e;let t=[ce.join(Jo,"..","templates"),ce.join(Jo,"..","..","templates")];for(let n of t)if(Z.existsSync(n))return n;return t[0]}function er(e,t){let n=[],o=Ia(t.templatesRoot),r=ce.join(e,"LICENSE");if(Z.existsSync(r)){let p=Z.readFileSync(r,"utf-8").slice(0,256);(/GNU AFFERO GENERAL PUBLIC LICENSE/i.test(p)||/Functional Source License/i.test(p))&&(Z.renameSync(r,ce.join(e,"LICENSE-UPSTREAM-REFERENCE.md")),n.push("LICENSE-UPSTREAM-REFERENCE.md (preserved upstream licence)"))}let s=ce.join(o,"LICENSE-SCAFFOLD.md");if(!Z.existsSync(s))throw new Error(`LICENSE-SCAFFOLD.md template missing at ${s}; cannot emit license.`);Z.copyFileSync(s,ce.join(e,"LICENSE")),n.push("LICENSE");let i={schemaVersion:1,cliVersion:t.cliVersion,scaffoldedAt:new Date().toISOString(),projectName:t.projectName,purpose:"Records which `create-sailor` version produced this project, for support triage. Provenance only: the MIT licence in LICENSE applies unconditionally and does not depend on this file. Deleting it costs you nothing.",license:{tier:"mit-scaffold",file:"LICENSE"}},a=ce.join(e,Zo);Z.mkdirSync(a,{recursive:!0}),Z.writeFileSync(ce.join(a,Qo),`${JSON.stringify(i,null,2)}
1518
+ `),n.push(`${Zo}/${Qo}`);let c=ce.join(e,"README.md");if(Z.existsSync(c)){let p=Z.readFileSync(c,"utf-8");p.includes("Scaffolded by `create-sailor`")||(Z.writeFileSync(c,`> **License notice:** Scaffolded by \`create-sailor\`. The Nebutra-Sailor
1519
1519
  > code in this project is [MIT licensed](./LICENSE) \u2014 commercial use, closed
1520
1520
  > source, no fee, no attribution required. The upstream monorepo is
1521
1521
  > FSL-1.1-ALv2 \u2014 see \`LICENSE-UPSTREAM-REFERENCE.md\`.
1522
1522
 
1523
- `+p),n.push("README.md (prepended license notice)"))}return{wrote:n}}import 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";
1523
+ `+p),n.push("README.md (prepended license notice)"))}return{wrote:n}}import Ve from"fs";import hn from"path";async function tr(e,t){let n=hn.join(e,"packages","mcp");if(t==="off"){Ve.existsSync(n)&&Ve.rmSync(n,{recursive:!0,force:!0});let r=hn.join(e,"packages","cli","src","commands","mcp-server.ts");Ve.existsSync(r)&&Ve.rmSync(r,{force:!0});return}let o=hn.join(e,".env.example");if(Ve.existsSync(o)){let r=Ve.readFileSync(o,"utf-8"),s="# MCP Server (Agent-friendly API)";if(!r.includes(s)){let i=["","# =============================================",s,"# Docs: https://modelcontextprotocol.io","# =============================================","# MCP server exposes your SaaS capabilities to AI agents via MCP protocol.","# Run: pnpm mcp-server (starts stdio server)","# No config required for stdio transport. HTTP transport needs:",'MCP_HTTP_PORT="3100"','MCP_API_KEY=""',""].join(`
1524
+ `);Ve.appendFileSync(o,i)}}}import vt from"fs";import nr from"path";async function or(e,t,n){let o=nr.join(e,"packages","metering"),r;if(t==="auto"?r=n!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){vt.existsSync(o)&&vt.rmSync(o,{recursive:!0,force:!0});return}let s=nr.join(e,".env.example");if(!vt.existsSync(s))return;let i=vt.readFileSync(s,"utf-8"),a="# Metering (usage-based billing)";if(!i.includes(a)){let c=["","# =============================================",a,"# Docs: see packages/commerce/metering/README.md","# =============================================","# ClickHouse-based metering pipeline for consumption billing.",'CLICKHOUSE_URL=""','CLICKHOUSE_USER="default"','CLICKHOUSE_PASSWORD=""','CLICKHOUSE_DATABASE="metering"',""].join(`
1525
+ `);vt.appendFileSync(s,c)}}import me from"fs";import F from"path";var rr=[{id:"sentry",name:"Sentry",region:"both",envVars:["SENTRY_DSN","NEXT_PUBLIC_SENTRY_DSN"],docs:"https://docs.sentry.io",pkg:"@sentry/nextjs",instrumentationFile:"apps/web/instrumentation.ts"},{id:"datadog",name:"Datadog",region:"global",envVars:["DD_API_KEY","DD_APP_KEY","DD_SITE"],docs:"https://docs.datadoghq.com",pkg:"dd-trace",instrumentationFile:"apps/web/instrumentation.ts"},{id:"bugsnag",name:"Bugsnag",region:"global",envVars:["BUGSNAG_API_KEY","NEXT_PUBLIC_BUGSNAG_API_KEY"],docs:"https://docs.bugsnag.com",pkg:"@bugsnag/js",instrumentationFile:"apps/web/src/lib/monitoring/bugsnag.ts"},{id:"aliyun-arms",name:"\u963F\u91CC\u4E91 ARMS",region:"cn",envVars:["ALIYUN_ARMS_LICENSE_KEY","ALIYUN_ARMS_APP_NAME","NEXT_PUBLIC_ARMS_PID"],docs:"https://help.aliyun.com/product/34364.html",instrumentationFile:"apps/web/src/components/monitoring/ArmsScript.tsx"},{id:"tingyun",name:"\u542C\u4E91 TingYun",region:"cn",envVars:["TINGYUN_LICENSE_KEY","NEXT_PUBLIC_TINGYUN_APP_KEY"],docs:"https://www.tingyun.com/docs",instrumentationFile:"apps/web/src/components/monitoring/TingYunScript.tsx"},{id:"none",name:"None",region:"both",envVars:[],docs:""}],Ud=rr.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function sr(e){return rr.find(t=>t.id===e)}var En={sentry:{"@sentry/nextjs":"^8.45.0"},datadog:{"dd-trace":"^5.32.0","@datadog/browser-rum":"^5.30.0"},bugsnag:{"@bugsnag/js":"^8.2.0","@bugsnag/plugin-react":"^8.2.0"}};function xa(e){me.mkdirSync(e,{recursive:!0})}function vn(e,t){let n=F.join(e,"package.json");if(!me.existsSync(n))return;let o;try{o=JSON.parse(me.readFileSync(n,"utf-8"))}catch(a){console.error(`Failed to parse ${n}:`,a);return}let s={...o.dependencies??{}};for(let[a,c]of Object.entries(t))s[a]||(s[a]=c);let i={...o,dependencies:s};me.writeFileSync(n,JSON.stringify(i,null,2)+`
1526
+ `)}function pe(e,t){xa(F.dirname(e)),me.writeFileSync(e,t)}function bt(e,t){let n=F.join(e,".env.example");me.existsSync(n)?me.appendFileSync(n,`
1527
+ `+t):me.writeFileSync(n,t)}function Ra(e){let t=`import * as Sentry from "@sentry/nextjs";
1528
1528
 
1529
1529
  Sentry.init({
1530
1530
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
@@ -1567,14 +1567,14 @@ export async function register() {
1567
1567
  }
1568
1568
 
1569
1569
  export { captureRequestError as onRequestError } from "@sentry/nextjs";
1570
- `;pe(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
1570
+ `;pe(F.join(e,"sentry.client.config.ts"),t),pe(F.join(e,"sentry.server.config.ts"),n),pe(F.join(e,"sentry.edge.config.ts"),o),pe(F.join(e,"instrumentation.ts"),r)}function Ta(){return`# Sentry \u2014 error tracking + performance monitoring
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 Ra(e){let t=`/**
1577
+ `}function ka(e){let t=`/**
1578
1578
  * Next.js instrumentation hook \u2014 wires Datadog APM (dd-trace) into Node runtime.
1579
1579
  * Edge runtime is not supported by dd-trace; only nodejs is initialized.
1580
1580
  */
@@ -1622,7 +1622,7 @@ export function initDatadogRum(): void {
1622
1622
  });
1623
1623
  initialized = true;
1624
1624
  }
1625
- `;pe(j.join(e,"instrumentation.ts"),t),pe(j.join(e,"src","lib","monitoring","datadog-rum.ts"),n)}function Ta(){return`# Datadog \u2014 APM + RUM
1625
+ `;pe(F.join(e,"instrumentation.ts"),t),pe(F.join(e,"src","lib","monitoring","datadog-rum.ts"),n)}function Na(){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 ka(e){let t=`/**
1640
+ `}function Oa(e){let t=`/**
1641
1641
  * Bugsnag server-side initialization.
1642
1642
  * Import this once at the top of your server entrypoint or a shared init module.
1643
1643
  */
@@ -1686,11 +1686,11 @@ export function getBugsnagErrorBoundary() {
1686
1686
  errorBoundary = plugin.createErrorBoundary(React) as typeof errorBoundary;
1687
1687
  return errorBoundary;
1688
1688
  }
1689
- `;pe(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
1689
+ `;pe(F.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),pe(F.join(e,"src","lib","monitoring","bugsnag.client.tsx"),n)}function La(){return`# Bugsnag \u2014 error tracking
1690
1690
  BUGSNAG_API_KEY=
1691
1691
  NEXT_PUBLIC_BUGSNAG_API_KEY=
1692
1692
  APP_VERSION=
1693
- `}function Oa(e){pe(j.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1693
+ `}function Ua(e){pe(F.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
1694
1694
  /**
1695
1695
  * \u963F\u91CC\u4E91 ARMS (Application Real-time Monitoring Service) browser agent.
1696
1696
  * Injects the official JS agent via next/script.
@@ -1711,11 +1711,11 @@ export function ArmsScript() {
1711
1711
  />
1712
1712
  );
1713
1713
  }
1714
- `)}function La(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
1714
+ `)}function Da(){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 Ua(e){pe(j.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1718
+ `}function Ma(e){pe(F.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
1719
1719
  /**
1720
1720
  * \u542C\u4E91 Browser Agent (\u524D\u7AEF\u6027\u80FD\u76D1\u63A7).
1721
1721
  * Docs: https://www.tingyun.com/docs
@@ -1733,12 +1733,12 @@ export function TingYunScript() {
1733
1733
  />
1734
1734
  );
1735
1735
  }
1736
- `)}function Da(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1736
+ `)}function Fa(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
1737
1737
  TINGYUN_LICENSE_KEY=
1738
1738
  NEXT_PUBLIC_TINGYUN_APP_KEY=
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
1739
+ `}async function ir(e,t,n="global"){let o=sr(t);if(!o||o.id==="none")return;let r=F.join(e,"apps","web");if(!me.existsSync(r))return;let s=o.id;try{switch(s){case"sentry":Ra(r),vn(r,En.sentry),bt(e,Ta());return;case"datadog":ka(r),vn(r,En.datadog),bt(e,Na());return;case"bugsnag":Oa(r),vn(r,En.bugsnag),bt(e,La());return;case"aliyun-arms":Ua(r),bt(e,Da());return;case"tingyun":Ma(r),bt(e,Fa());return;default:return}}catch(i){throw console.error(`Failed to apply monitoring selection "${t}":`,i),new Error(`Monitoring scaffold for "${t}" failed \u2014 see stderr for details.`)}}var Mt=[{id:"novu",name:"Novu",region:"both",envVars:["NOVU_API_KEY","NOVU_APPLICATION_IDENTIFIER"],docs:"https://docs.novu.co",description:"Multi-channel notification infrastructure"},{id:"knock",name:"Knock",region:"global",envVars:["KNOCK_API_KEY","KNOCK_SIGNING_KEY","KNOCK_PUBLIC_API_KEY"],docs:"https://docs.knock.app",description:"Product notifications platform"},{id:"custom",name:"Custom (direct dispatchers)",region:"both",envVars:[],docs:"",description:"Use email + sms + push directly"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function ar(e){return Mt.find(t=>t.id===e)}var Vd=Mt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function cr(e,t,n="global"){let o=ar(t);if(!o)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${Mt.map(r=>r.id).join(", ")}`);if(o.id==="none"){J(e,"notifications");return}o.envVars.length>0&&re(e,{category:"Notifications",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"NOTIFICATIONS_PROVIDER",o.id)}import bn from"fs";import ja from"path";async function pr(e,t){let n=ja.join(e,"package.json");if(bn.existsSync(n)){let o=bn.readFileSync(n,"utf8"),r=JSON.parse(o);r.name=t,r.version="0.1.0",bn.writeFileSync(n,JSON.stringify(r,null,2)+`
1740
+ `)}}import Ft from"fs";import st from"path";import{fileURLToPath as Ba}from"url";var Va=Ba(import.meta.url),lr=st.dirname(Va);function $a(){let e=[st.join(lr,"..","templates","orm","drizzle"),st.join(lr,"..","..","templates","orm","drizzle")];for(let t of e)if(Ft.existsSync(t))return t;return null}function dr(e,t){Ft.mkdirSync(t,{recursive:!0});for(let n of Ft.readdirSync(e,{withFileTypes:!0})){let o=st.join(e,n.name),r=st.join(t,n.name);n.isDirectory()?dr(o,r):Ft.copyFileSync(o,r)}}async function ur(e,t,n){if(t!=="drizzle")return{applied:!1};if(n!=="postgresql")return{applied:!1,reason:`Drizzle template currently targets Postgres only; --db=${n} keeps Prisma as sole ORM`};let o=$a();if(!o)return{applied:!1,reason:"Drizzle template directory not found in package \u2014 bundling error"};let r=st.join(e,"packages","platform","db-drizzle");return dr(o,r),{applied:!0}}import ge from"fs";import _t from"path";var Ka=["stripe","lemonsqueezy","chinapay","polar"];function mr(e){ge.existsSync(e)&&ge.rmSync(e,{recursive:!0,force:!0})}function Ya(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function qa(e,t){let n=_t.join(e,".env.example");ge.existsSync(n)?ge.appendFileSync(n,`
1741
+ `+t):ge.writeFileSync(n,t)}function Ga(e){switch(e){case"stripe":return`# Stripe
1742
1742
  STRIPE_SECRET_KEY=
1743
1743
  STRIPE_WEBHOOK_SECRET=
1744
1744
  `;case"lemon":return`# Lemon Squeezy
@@ -1753,13 +1753,13 @@ CHINAPAY_WECHAT_ENABLED=true
1753
1753
  CHINAPAY_APP_ID=
1754
1754
  CHINAPAY_APP_SECRET=
1755
1755
  CHINAPAY_ALIPAY_ENABLED=true
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)+`
1756
+ `}}async function gr(e,t){let n=_t.join(e,"packages","commerce","billing");if(!ge.existsSync(n))return;if(t==="none"){mr(n);return}let o=_t.join(n,"src"),r=new Set(Ya(t));for(let i of Ka)r.has(i)||mr(_t.join(o,i));let s=_t.join(o,"checkout","types.ts");if(ge.existsSync(s)){let i=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",a=ge.readFileSync(s,"utf8"),c=a.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${i}";`);c!==a&&ge.writeFileSync(s,c)}qa(e,Ga(t))}import we from"fs";import it from"path";var Sr=new Set(["siliconflow","volcengine-ark","bailian","moonshot","sensetime"]),_n=/@sailor:([^\s*]+)/;function Ha(e,t){let{providerIds:n,customEndpoint:o}=t;if(e.startsWith("provider:")){let r=e.slice(9);return{marker:e,keep:n.includes(r)}}if(e==="cn-compatible"){let r=n.some(s=>Sr.has(s));return{marker:e,keep:r||!!o}}if(e.startsWith("cn-instance:")){let r=e.slice(12);return{marker:e,keep:n.includes(r)}}return e==="custom-endpoint"?{marker:e,keep:!!o}:e==="registry-entries"?{marker:e,keep:!0}:{marker:e,keep:!0}}function fr(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function yr(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function hr(e,t){let n=e.split(`
1757
+ `),o=[],r=e.includes("#"),s=0;for(;s<n.length;){let i=n[s],a=i.match(_n);if(!a){o.push(i),s++;continue}let{marker:c,keep:p}=Ha(a[1],t);if(c==="registry-entries"){o.push(r?yr(i):fr(i)),s++;continue}if(p){let d=r?yr(i):fr(i);d.trim().length>0&&o.push(d);let u=s+1;for(;u<n.length&&n[u].trim()!==""&&!_n.test(n[u]);)o.push(n[u]),u++;u<n.length&&n[u].trim()===""&&(o.push(n[u]),u++),s=u}else{let d=s+1;for(;d<n.length&&n[d].trim()!==""&&!_n.test(n[d]);)d++;d<n.length&&n[d].trim()===""&&d++,s=d}}return Wa(o.join(`
1758
+ `),t)}function Wa(e,t){let{providerIds:n,customEndpoint:o}=t,r=new Set;for(let p of n)["openai","anthropic","google","mistral","xai"].includes(p)&&r.add(p),r.add(p.replace(/-/g,"_")),r.add(p);o&&r.add("custom");let s=/createProviderRegistry\(\{([\s\S]*?)\}\)/,i=e.match(s);if(!i)return e;let c=i[1].split(`
1759
+ `).filter(p=>{let d=p.trim();if(d===""||d.startsWith("//"))return!0;let u=d.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return u?r.has(u[1]):!0}).join(`
1760
+ `);return e.replace(s,`createProviderRegistry({${c}})`)}function Xa(e,t){let n=it.join(t,"registry.ts.template"),o=we.readFileSync(n,"utf-8");return hr(o,e)}function za(e,t){let n=it.join(t,".env.example.template"),o=we.readFileSync(n,"utf-8");return hr(o,e)}async function Er(e,t,n){let o=Xa(t,n),r=za(t,n),s=it.join(e,"packages/ai/agents/src");await we.promises.mkdir(s,{recursive:!0}),await we.promises.writeFile(it.join(s,"registry.ts"),o),await we.promises.appendFile(it.join(e,".env.example"),`
1761
+ `+r);let i={ai:"latest"},{providerIds:a,customEndpoint:c}=t;(a.includes("openai")||c||a.some(d=>Sr.has(d)))&&(i["@ai-sdk/openai"]="latest",i["@ai-sdk/openai-compatible"]="latest"),a.includes("anthropic")&&(i["@ai-sdk/anthropic"]="latest"),a.includes("google")&&(i["@ai-sdk/google"]="latest"),a.includes("mistral")&&(i["@ai-sdk/mistral"]="latest"),a.includes("xai")&&(i["@ai-sdk/openai"]="latest");let p=it.join(e,"package.json");if(we.existsSync(p)){let d=JSON.parse(await we.promises.readFile(p,"utf-8"));d.dependencies||(d.dependencies={});for(let[u,A]of Object.entries(i))d.dependencies[u]=A;await we.promises.writeFile(p,JSON.stringify(d,null,2)+`
1762
+ `)}}import y from"fs";import f from"path";function vr(e,t){if(!y.existsSync(e))return;let n=y.readdirSync(e);for(let o of n){let r=f.join(e,o);y.statSync(r).isDirectory()?vr(r,t):t(r)}}async function br(e,t){let n=f.join(e,"package.json");if(!y.existsSync(n))return;let o=JSON.parse(y.readFileSync(n,"utf8"));if(t.orm!=="prisma"){let r=f.join(e,"packages","db");if(y.existsSync(r)){let s=f.join(r,"prisma");y.existsSync(s)&&y.rmSync(s,{recursive:!0,force:!0});let i=f.join(r,"package.json");if(y.existsSync(i)){let c=JSON.parse(y.readFileSync(i,"utf8"));c.dependencies&&delete c.dependencies["@prisma/client"],c.devDependencies&&delete c.devDependencies.prisma,y.writeFileSync(i,JSON.stringify(c,null,2)+`
1763
1763
  `)}let a=f.join(r,"src","index.ts");y.existsSync(a)&&y.writeFileSync(a,`
1764
1764
  export const prisma = {} as any;
1765
1765
  export const db = {} as 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=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,`
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 m=f.join(c,S);if(y.existsSync(m)){let _=y.readdirSync(m);for(let H of _)y.renameSync(f.join(m,H),f.join(c,H));y.rmdirSync(m)}}),["src/middleware.ts","middleware.ts"].forEach(S=>{let m=f.join(a,S);y.existsSync(m)&&y.rmSync(m)});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 C=f.join(p,"mock-i18n.d.ts");y.writeFileSync(C,`declare module '@/lib/mock-i18n' {
1827
+ `);let A=f.join(p,"mock-i18n.d.ts");y.writeFileSync(A,`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>;
@@ -1845,16 +1845,16 @@ export function defineRouting<T>(config: T): T { return config; }
1845
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 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": {
1848
+ `);let h=f.join(a,"tsconfig.json");if(y.existsSync(h))try{let S=y.readFileSync(h,"utf8");if(S.includes('"paths": {')){let m=S.replace(/"paths":\s*\{/,`"paths": {
1849
1849
  "next-intl": ["./src/lib/mock-i18n"],
1850
- "next-intl/*": ["./src/lib/mock-i18n"],`);y.writeFileSync(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)+`
1850
+ "next-intl/*": ["./src/lib/mock-i18n"],`);y.writeFileSync(h,m)}}catch{}let g=f.join(a,"src");y.existsSync(g)&&vr(g,S=>{if(!S.endsWith(".ts")&&!S.endsWith(".tsx"))return;let m=y.readFileSync(S,"utf8"),_=!1;S.endsWith("src/app/layout.tsx")&&m.includes("../providers")&&(m=m.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),_=!0),m=m.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),m=m.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),m.match(/locale\s*:\s*any/)&&(m=m.replace(/locale\s*:\s*any/g,"locale: string"),_=!0),m.match(/lang\s*:\s*any/)&&(m=m.replace(/lang\s*:\s*any/g,"lang: string"),_=!0),m.match(/requestLocale\s*:\s*any/)&&(m=m.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),_=!0),m.match(/\(locale\s*=\s*(.*)\)/)&&(m=m.replace(/\(locale\s*=\s*(.*)\)/g,"() "),_=!0),m.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(m=m.replace(/export\s+default\s+async\s+function\s+LangLayout\s*\(\s*\{\s*children\s*,\s*params\s*\}\s*:\s*LangLayoutProps\s*\)/g,"export default async function LangLayout({ children }: { children: React.ReactNode })"),_=!0),(S.endsWith("src/app/layout.tsx")||S.endsWith("src/app/sitemap.ts")||S.endsWith("src/app/robots.ts")||S.endsWith("src/components/ui/locale-switcher.tsx")||S.endsWith("src/app/(marketing)/blog/[slug]/page.tsx"))&&(m=m.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),m=m.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),m=m.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),m=m.replace(/\(l\)\s*=>/g,"(l: any) =>"),_=!0),S.endsWith("src/i18n/request.ts")&&(m=m.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),_=!0),(m.match(/locale\s*:/)||m.match(/lang\s*:/))&&(_=!0),_&&y.writeFileSync(S,m)});let E=f.join(a,"package.json");if(y.existsSync(E)){let S=JSON.parse(y.readFileSync(E,"utf8"));S.dependencies&&delete S.dependencies["next-intl"],y.writeFileSync(E,JSON.stringify(S,null,2)+`
1851
1851
  `)}}}}y.writeFileSync(n,JSON.stringify(o,null,2)+`
1852
- `)}function b(e){try{y.rmSync(e,{recursive:!0,force:!0})}catch{}}function 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 {
1852
+ `)}function b(e){try{y.rmSync(e,{recursive:!0,force:!0})}catch{}}function Ja(e,t){if(!y.existsSync(e))return;let n;try{n=JSON.parse(y.readFileSync(e,"utf8"))}catch{return}let o=!1;if(n.dependencies&&t in n.dependencies){let{[t]:r,...s}=n.dependencies;n={...n,dependencies:s},o=!0}if(n.devDependencies&&t in n.devDependencies){let{[t]:r,...s}=n.devDependencies;n={...n,devDependencies:s},o=!0}o&&y.writeFileSync(e,JSON.stringify(n,null,2)+`
1853
+ `)}function _r(e,t){t.cronJobs||(b(f.join(e,"apps/web/src/app/api/cron")),b(f.join(e,"packages/integrations/queue/src/scheduled"))),t.auditLog||(b(f.join(e,"apps/web/src/app/[locale]/(app)/settings/audit-log")),b(f.join(e,"apps/web/src/app/api/audit-logs")),b(f.join(e,"apps/web/src/components/audit"))),t.apiKeys||(b(f.join(e,"apps/web/src/app/[locale]/(app)/settings/api-keys")),b(f.join(e,"apps/web/src/app/api/api-keys")),b(f.join(e,"apps/web/src/components/api-keys"))),t.webhooks||(b(f.join(e,"apps/web/src/app/[locale]/(app)/settings/webhooks")),b(f.join(e,"apps/web/src/app/api/webhooks")),b(f.join(e,"apps/web/src/components/webhooks")),b(f.join(e,"packages/integrations/webhooks"))),t.commandPalette||(b(f.join(e,"apps/web/src/components/command-palette")),b(f.join(e,"apps/web/src/app/[locale]/providers/command-palette-mount.tsx"))),t.cookieConsent||(b(f.join(e,"apps/landing/src/components/cookie-consent-banner.tsx")),b(f.join(e,"apps/landing/src/components/__tests__/cookie-consent-banner.test.tsx")),b(f.join(e,"apps/landing/src/lib/cookie-consent.ts")),b(f.join(e,"apps/landing/src/lib/__tests__/cookie-consent.test.ts")),b(f.join(e,"apps/web/src/app/api/cookie-consent"))),t.legalPages||(b(f.join(e,"apps/landing/src/app/[lang]/(legal)/legal")),b(f.join(e,"apps/landing/src/lib/legal-documents.ts")),b(f.join(e,"apps/landing/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(b(f.join(e,"packages/ops/china-compliance")),b(f.join(e,"apps/landing/src/components/icp-footer.tsx")),b(f.join(e,"apps/landing/src/components/__tests__/icp-footer.test.tsx")),b(f.join(e,"apps/web/src/components/auth/wechat-login-button.tsx")),b(f.join(e,"apps/web/src/components/auth/__tests__/wechat-login-button.test.tsx")),Ja(f.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import at from"fs";import Pr from"path";var wr=/^--\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/m;function Qa(e){let t=wr.exec(e);if(!t)return null;let[,n,o]=t,r=o.split("|").map(s=>s.trim()).filter(Boolean);return{flag:n,values:r}}function Za(e){return e.replace(wr,"").replace(/^\n/,"")}function Pn(e,t){let n={kept:[],removed:[],skipped:[]};if(!at.existsSync(e))return n;let o=at.readdirSync(e,{withFileTypes:!0}).filter(r=>r.isDirectory()).sort((r,s)=>r.name.localeCompare(s.name));for(let r of o){let s=Pr.join(e,r.name),i=Pr.join(s,"migration.sql");if(!at.existsSync(i)){n.skipped.push(r.name);continue}let a=at.readFileSync(i,"utf8"),c=Qa(a);if(!c){n.skipped.push(r.name);continue}let p=t[c.flag];if(p!==void 0&&c.values.includes(p)){at.writeFileSync(i,Za(a)),n.kept.push(r.name);continue}at.rmSync(s,{recursive:!0,force:!0}),n.removed.push(r.name)}return n}import{getSchema as ec,printSchema as tc}from"@mrleebo/prisma-ast";var nc=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function oc(e){return e.type==="comment"&&e.text.trim().startsWith("//")}function rc(e){let t=nc.exec(e.trim());if(!t)return null;let[,n,o]=t,r=o.split("|").map(s=>s.trim()).filter(s=>s.length>0);return{flag:n,values:r}}function sc(e,t){for(let n=t-1;n>=0;n--){let o=e[n];if(o.type==="comment"){let r=rc(o.text);if(r)return{annIndex:n,parsed:r};continue}break}return null}function ic(e){return e.type==="model"||e.type==="enum"}function wn(e,t){let n=ec(e),o=new Set;for(let a=0;a<n.list.length;a++){let c=n.list[a];if(!ic(c))continue;let p=sc(n.list,a);if(!p)continue;let d=t[p.parsed.flag];if(d!==void 0&&p.parsed.values.includes(d))o.add(p.annIndex);else{o.add(a);for(let h=a-1;h>=0;h--){let g=n.list[h];if(oc(g)){o.add(h);continue}break}let A=n.list[a+1];A&&A.type==="break"&&o.add(a+1)}}let r=n.list.filter((a,c)=>!o.has(c)),s=[];for(let a of r){let c=s[s.length-1];a.type==="break"&&c&&c.type==="break"||s.push(a)}return tc({type:"schema",list:s})}import ct from"fs";import Cr from"path";var jt=[{id:"qstash",name:"Upstash QStash",region:"both",envVars:["QSTASH_TOKEN","QSTASH_CURRENT_SIGNING_KEY","QSTASH_NEXT_SIGNING_KEY"],docs:"https://upstash.com/docs/qstash",description:"Serverless HTTP-based queue"},{id:"bullmq",name:"BullMQ",region:"both",envVars:["REDIS_URL"],docs:"https://docs.bullmq.io",description:"Redis-backed job queue"},{id:"sqs",name:"AWS SQS",region:"global",envVars:["AWS_SQS_QUEUE_URL","AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_REGION"],docs:"https://docs.aws.amazon.com/AWSSimpleQueueService/",description:"AWS managed queue"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip queue package"}];function Ar(e){return jt.find(t=>t.id===e)}var mu=jt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ir(e){return ct.existsSync(e)?ct.readFileSync(e,"utf-8"):null}function ac(e,t){let n=Cr.join(e,".env.example"),o=Ir(n);if(o===null)return;let r=`# Queue: ${t.name}`;if(o.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1854
+ `);ct.appendFileSync(n,s)}function cc(e,t,n){let o=Cr.join(e,".env.example"),r=Ir(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?ct.writeFileSync(o,r.replace(s,`${t}="${n}"`)):ct.appendFileSync(o,`${t}="${n}"
1855
+ `)}async function xr(e,t,n){let o=Le(e,"queue");if(t==="none"){o&&ct.rmSync(o,{recursive:!0,force:!0});return}let r=Ar(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${jt.map(s=>s.id).join(", ")}`);o&&(ac(e,r),cc(e,"QUEUE_PROVIDER",t))}import fe from"fs";import Ae from"path";import{fileURLToPath as pc}from"url";var lc=pc(import.meta.url),Rr=Ae.dirname(lc),dc=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|toml|py)$/,uc=["backends/gateway","infra","e2e","tests"];function mc(){let e=[Ae.join(Rr,"..","templates"),Ae.join(Rr,"..","..","templates")];for(let t of e)if(fe.existsSync(t))return t;return e[0]}async function Tr(e,t){let n=mc(),o=[],r=[],s=[...uc,...t.withWorkflows?["workflows"]:[],...t.withPythonBackend?["backends/python"]:[]];for(let i of s){let a=Ae.join(n,i);if(!fe.existsSync(a)){r.push(i);continue}let c=Ae.join(e,i);kr(a,c),Nr(c,{"{PRODUCT_NAME}":t.projectName}),o.push(i)}return{applied:o,skipped:r}}function kr(e,t){fe.mkdirSync(t,{recursive:!0});for(let n of fe.readdirSync(e,{withFileTypes:!0})){let o=Ae.join(e,n.name),r=Ae.join(t,n.name);n.isDirectory()?kr(o,r):fe.existsSync(r)||fe.copyFileSync(o,r)}}function Nr(e,t){for(let n of fe.readdirSync(e,{withFileTypes:!0})){let o=Ae.join(e,n.name);if(n.isDirectory()){Nr(o,t);continue}if(!dc.test(n.name))continue;let r=fe.readFileSync(o,"utf-8"),s=!1;for(let[i,a]of Object.entries(t))r.includes(i)&&(r=r.split(i).join(a),s=!0);s&&fe.writeFileSync(o,r)}}import pt from"fs";import Lr from"path";var Bt=[{id:"meilisearch",name:"Meilisearch",region:"both",envVars:["MEILISEARCH_HOST","MEILISEARCH_MASTER_KEY"],docs:"https://docs.meilisearch.com",description:"Self-hostable search"},{id:"typesense",name:"Typesense",region:"both",envVars:["TYPESENSE_HOST","TYPESENSE_PORT","TYPESENSE_PROTOCOL","TYPESENSE_API_KEY"],docs:"https://typesense.org/docs",description:"Open-source search"},{id:"algolia",name:"Algolia",region:"global",envVars:["ALGOLIA_APP_ID","ALGOLIA_ADMIN_API_KEY","ALGOLIA_SEARCH_API_KEY"],docs:"https://www.algolia.com/doc/",description:"Managed search as a service"},{id:"pgvector",name:"pgvector (Postgres)",region:"both",envVars:["DATABASE_URL"],docs:"https://github.com/pgvector/pgvector",description:"Postgres vector + full-text"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip search package"}];function Or(e){return Bt.find(t=>t.id===e)}var wu=Bt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ur(e){return pt.existsSync(e)?pt.readFileSync(e,"utf-8"):null}function gc(e,t){let n=Lr.join(e,".env.example"),o=Ur(n);if(o===null)return;let r=`# Search: ${t.name}`;if(o.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
1856
+ `);pt.appendFileSync(n,s)}function fc(e,t,n){let o=Lr.join(e,".env.example"),r=Ur(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?pt.writeFileSync(o,r.replace(s,`${t}="${n}"`)):pt.appendFileSync(o,`${t}="${n}"
1857
+ `)}async function Dr(e,t,n){let o=Le(e,"search");if(t==="none"){o&&pt.rmSync(o,{recursive:!0,force:!0});return}let r=Or(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${Bt.map(s=>s.id).join(", ")}`);o&&(gc(e,r),fc(e,"SEARCH_PROVIDER",t))}import Ce from"fs";import $e from"path";function yc(e){let t=[$e.join(e,"packages","db"),$e.join(e,"apps","web")];for(let n of t){let o=$e.join(n,"prisma","schema.prisma");if(Ce.existsSync(o))return{packageDir:n,seedPath:$e.join(n,"prisma","seed.ts"),packageJsonPath:$e.join(n,"package.json")}}return null}function Sc(e){try{let t=Ce.readFileSync(e,"utf8"),n=new Set,o=/^\s*model\s+(\w+)\s*\{/gm,r=o.exec(t);for(;r;)n.add(r[1]),r=o.exec(t);return n}catch{return new Set}}function hc(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
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 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 }> = [];
1888
+ }`}function Ec(e,t){let n=t.has("Tenant"),o=t.has("User"),r=t.has("Project"),s=hc(e,o),i=n?` let tenants: Array<{ id: string; name: string }> = [];
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 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(`
1957
+ `}function vc(e){if(Ce.existsSync(e))try{let t=Ce.readFileSync(e,"utf8"),n=JSON.parse(t),o=n.scripts??{},r=!1;o["db:seed"]||(o["db:seed"]="prisma db seed",r=!0);let s=n.prisma??{};if(s.seed||(s.seed="tsx prisma/seed.ts",r=!0),!r)return;let i={...n,scripts:o,prisma:s};Ce.writeFileSync(e,JSON.stringify(i,null,2)+`
1958
+ `)}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`[create-sailor] Failed to patch seed scripts in ${e}: ${n}`)}}async function Mr(e,t){let n=yc(e);if(n)try{let o=$e.join(n.packageDir,"prisma","schema.prisma"),r=Sc(o),s=Ec(t,r),i=$e.dirname(n.seedPath);Ce.existsSync(i)||Ce.mkdirSync(i,{recursive:!0}),Ce.writeFileSync(n.seedPath,s),vc(n.packageJsonPath)}catch(o){let r=o instanceof Error?o.message:String(o);throw console.error(`[create-sailor] Failed to generate seed data: ${r}`),new Error(`Unable to write prisma/seed.ts: ${r}`)}}import Ie from"fs";import Ke from"path";var Vt=[{id:"twilio",name:"Twilio",region:"global",envVars:["TWILIO_ACCOUNT_SID","TWILIO_AUTH_TOKEN","TWILIO_FROM_NUMBER"],docs:"https://www.twilio.com/docs/sms",pkgs:["twilio"]},{id:"messagebird",name:"MessageBird (Bird)",region:"global",envVars:["MESSAGEBIRD_ACCESS_KEY","MESSAGEBIRD_ORIGINATOR"],docs:"https://developers.messagebird.com/api/sms-messaging/",pkgs:["messagebird"]},{id:"plivo",name:"Plivo",region:"global",envVars:["PLIVO_AUTH_ID","PLIVO_AUTH_TOKEN","PLIVO_FROM_NUMBER"],docs:"https://www.plivo.com/docs/sms/",pkgs:["plivo"]},{id:"aliyun-sms",name:"\u963F\u91CC\u4E91\u77ED\u4FE1 Aliyun SMS",region:"cn",envVars:["ALIYUN_SMS_ACCESS_KEY","ALIYUN_SMS_ACCESS_SECRET","ALIYUN_SMS_SIGN_NAME","ALIYUN_SMS_TEMPLATE_CODE","ALIYUN_SMS_ENDPOINT"],docs:"https://help.aliyun.com/product/44282.html",pkgs:["@alicloud/dysmsapi20170525","@alicloud/openapi-client"]},{id:"tencent-sms",name:"\u817E\u8BAF\u4E91\u77ED\u4FE1 Tencent SMS",region:"cn",envVars:["TENCENT_SMS_SECRET_ID","TENCENT_SMS_SECRET_KEY","TENCENT_SMS_SDK_APP_ID","TENCENT_SMS_SIGN_NAME","TENCENT_SMS_TEMPLATE_ID","TENCENT_SMS_REGION"],docs:"https://cloud.tencent.com/document/product/382",pkgs:["tencentcloud-sdk-nodejs-sms"]},{id:"yunpian",name:"\u4E91\u7247 Yunpian",region:"cn",envVars:["YUNPIAN_API_KEY","YUNPIAN_SIGN"],docs:"https://www.yunpian.com/official/document/sms/zh_CN/introduction_product_intro",pkgs:["yunpian-nodejs-sdk"]},{id:"none",name:"None",region:"both",envVars:[],docs:""}],Lu=Vt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Fr(e){return Vt.find(t=>t.id===e)}var bc="@nebutra/sms",_c={twilio:"^5.3.6",messagebird:"^4.0.1",plivo:"^4.73.0","@alicloud/dysmsapi20170525":"^2.0.24","@alicloud/openapi-client":"^0.4.12","tencentcloud-sdk-nodejs-sms":"^4.0.970","yunpian-nodejs-sdk":"^0.0.2"};function An(e,t){Ie.mkdirSync(Ke.dirname(e),{recursive:!0}),Ie.writeFileSync(e,t)}function Pc(e,t){let n=Ke.join(e,".env.example");Ie.existsSync(n)?Ie.appendFileSync(n,`
1959
+ `+t):Ie.writeFileSync(n,t)}function wc(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
1960
1960
  `);return`${t}
1961
1961
  ${n}
1962
- `}var Pc=`/**
1962
+ `}var Ac=`/**
1963
1963
  * Inputs for the \`sendSms\` wrapper. Keep this surface portable across
1964
1964
  * providers \u2014 provider-specific options belong in the wrapper itself.
1965
1965
  */
@@ -1979,7 +1979,7 @@ export interface SendSmsResult {
1979
1979
  provider: string;
1980
1980
  raw?: unknown;
1981
1981
  }
1982
- `;function wc(){return`import twilio from "twilio";
1982
+ `;function Cc(){return`import twilio from "twilio";
1983
1983
  import type { SendSmsInput, SendSmsResult } from "./types";
1984
1984
 
1985
1985
  let client: ReturnType<typeof twilio> | null = null;
@@ -2014,7 +2014,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
2014
2014
  }
2015
2015
 
2016
2016
  export type { SendSmsInput, SendSmsResult } from "./types";
2017
- `}function Ac(){return`import messagebird from "messagebird";
2017
+ `}function Ic(){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 Cc(){return`import plivo from "plivo";
2055
+ `}function xc(){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 Ic(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
2094
+ `}function Rc(){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 xc(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
2143
+ `}function Tc(){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 Rc(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
2208
+ `}function kc(){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 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(`
2260
+ `}function Nc(e){switch(e){case"twilio":return Cc();case"messagebird":return Ic();case"plivo":return xc();case"aliyun-sms":return Rc();case"tencent-sms":return Tc();case"yunpian":return kc();case"none":return`export {};
2261
+ `}}function Oc(e){let t={};for(let o of e.pkgs??[]){let r=_c[o];r&&(t[o]=r)}let n={name:bc,version:"0.1.0",private:!0,description:`Transactional SMS via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
2262
+ `}async function jr(e,t,n="global"){if(t==="none")return;let o=Fr(t);if(!o)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${Vt.map(i=>i.id).join(", ")}`);let r=Ke.join(e,"packages","sms");if(!Ie.existsSync(r))return;let s=Ke.join(r,"src");Ie.existsSync(s)&&Ie.rmSync(s,{recursive:!0,force:!0});try{An(Ke.join(r,"package.json"),Oc(o)),An(Ke.join(s,"types.ts"),Ac),An(Ke.join(s,"index.ts"),Nc(o.id)),Pc(e,wc(o))}catch(i){throw console.error(`Failed to apply SMS selection "${t}":`,i),new Error(`SMS scaffold for "${t}" failed \u2014 see stderr for details.`)}}import qe from"fs";import Ye from"path";var Ge="@nebutra/storage";function Cn(e,t){qe.mkdirSync(Ye.dirname(e),{recursive:!0}),qe.writeFileSync(e,t)}function Lc(e,t){let n=Ye.join(e,".env.example");qe.existsSync(n)?qe.appendFileSync(n,`
2263
+ `+t):qe.writeFileSync(n,t)}function Uc(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
2264
2264
  `);return`${t}
2265
2265
  ${n}
2266
- `}var Lc=`/**
2266
+ `}var Dc=`/**
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 Uc(){return`/**
2293
- * @${qe.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
2292
+ `;function Mc(){return`/**
2293
+ * @${Ge.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
2294
2294
  *
2295
2295
  * Docs: https://developers.cloudflare.com/r2/api/s3/api/
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 Dc(){return`/**
2357
- * @${qe.slice(1)} \u2014 AWS S3 wrapper.
2356
+ `}function Fc(){return`/**
2357
+ * @${Ge.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 Mc(){return`/**
2422
- * @${qe.slice(1)} \u2014 Supabase Storage wrapper.
2421
+ `}function jc(){return`/**
2422
+ * @${Ge.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 Fc(){return`/**
2485
- * @${qe.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2484
+ `}function Bc(){return`/**
2485
+ * @${Ge.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
2486
2486
  *
2487
2487
  * Docs: https://help.aliyun.com/product/31815.html
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 jc(){return`/**
2532
- * @${qe.slice(1)} \u2014 \u817E\u8BAF\u4E91 COS wrapper via cos-nodejs-sdk-v5.
2531
+ `}function Vc(){return`/**
2532
+ * @${Ge.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 Bc(){return`/**
2587
- * @${qe.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
2586
+ `}function $c(){return`/**
2587
+ * @${Ge.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 $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";
2654
+ `}function Kc(e){switch(e){case"r2":return Mc();case"s3":return Fc();case"supabase-storage":return jc();case"aliyun-oss":return Bc();case"tencent-cos":return Vc();case"qiniu":return $c();case"none":return`export {};
2655
+ `}}function Yc(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),(e.id==="r2"||e.id==="s3")&&(t["@aws-sdk/s3-request-presigner"]="^3.658.0");let n={name:Ge,version:"0.1.0",private:!0,description:`Object storage via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
2656
+ `}async function Br(e,t,n){if(t==="none")return;let o=$n(t);if(!o)throw new Error(`Unknown storage provider "${t}". Valid ids: ${Re.map(i=>i.id).join(", ")}`);let r=Ye.join(e,"packages","storage"),s=Ye.join(r,"src");qe.existsSync(s)&&qe.rmSync(s,{recursive:!0,force:!0}),Cn(Ye.join(r,"package.json"),Yc(o)),Cn(Ye.join(s,"types.ts"),Dc),Cn(Ye.join(s,"index.ts"),Kc(o.id)),Lc(e,Uc(o))}var $t=[{id:"svix",name:"Svix",region:"global",envVars:["SVIX_API_TOKEN"],docs:"https://docs.svix.com",description:"Managed webhooks platform"},{id:"custom",name:"Custom (self-hosted)",region:"both",envVars:["WEBHOOK_SIGNING_SECRET"],docs:"",description:"Custom implementation with built-in package"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Vr(e){return $t.find(t=>t.id===e)}var Yu=$t.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function $r(e,t,n="global"){let o=Vr(t);if(!o)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${$t.map(r=>r.id).join(", ")}`);if(o.id==="none"){J(e,"webhooks");return}o.envVars.length>0&&re(e,{category:"Webhooks",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"WEBHOOKS_PROVIDER",o.id)}import He from"fs";import Pt from"path";function qc(e){return`import { brand } from "@nebutra/brand/metadata";
2657
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 Yc(e={}){return`
2766
+ `}function Gc(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 qc(e=[]){return e.length===0?"":`
2771
+ `}function Hc(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=Qe(n.status);return`- ${n.flag}=${n.provider} ${o} \u2014 ${_e(n.status)}`}).join(`
2776
+ ${e.map(n=>{let o=et(n.status);return`- ${n.flag}=${n.provider} ${o} \u2014 ${Te(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 Gc(e,t,n=[],o={}){return`# Next steps \u2014 ${e}
2780
+ `}function Wc(e,t,n=[],o={}){return`# Next steps \u2014 ${e}
2781
2781
 
2782
2782
  Region: ${t}
2783
2783
 
@@ -2803,24 +2803,28 @@ 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
- ${Yc(o)}${qc(n)}
2806
+ ${Gc(o)}${Hc(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 $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.
2813
+ `}async function Kr(e,t){let{projectName:n,region:o,previewSelections:r=[],waveFeatures:s={}}=t;try{let i=Pt.join(e,".sailor");He.existsSync(i)||He.mkdirSync(i,{recursive:!0}),He.writeFileSync(Pt.join(i,"next-steps.md"),Wc(n,o,r,s))}catch(i){let a=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write .sailor/next-steps.md: ${a}`)}try{let i=Pt.join(e,"apps","web");if(!He.existsSync(i))return;let a=Pt.join(i,"src","app","[locale]","welcome");He.existsSync(a)||He.mkdirSync(a,{recursive:!0}),He.writeFileSync(Pt.join(a,"page.tsx"),qc(n))}catch(i){let a=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write welcome page: ${a}`)}}function l(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2814
+ `)}function Yr(e){return e!==null&&typeof e=="object"&&"code"in e&&e.code==="ENOENT"}function zc(e,t){for(let n of t)if(e)l(!0,{event:"warn",step:n.flag,provider:n.provider,packageStatus:n.status,message:Te(n.status)});else{let o=et(n.status);process.stdout.write(We.yellow(`\u26A0 ${n.flag}=${n.provider} ${o} \u2014 ${Te(n.status)}
2815
+ `))}}function Jc(e,t,n){let o=Xe.join(t,"packages/platform/db/prisma/schema.prisma"),r;try{r=Yt.readFileSync(o,"utf8")}catch(s){if(Yr(s)){l(e,{event:"step",step:"schema-prune",status:"skip"});return}let i=s instanceof Error?s.message:String(s);l(e,{event:"step",step:"schema-prune",status:"error",error:i});return}l(e,{event:"step",step:"schema-prune",status:"start"});try{let s=wn(r,n);Yt.writeFileSync(o,s),Pn(Xe.join(Xe.dirname(o),"migrations"),n),l(e,{event:"step",step:"schema-prune",status:"ok"})}catch(s){let i=s instanceof Error?s.message:String(s);l(e,{event:"step",step:"schema-prune",status:"error",error:i})}}async function qr(e){let{resolvedTarget:t,projectName:n,resolvedPm:o,opts:r,useJson:s,resolved:i,startedAt:a}=e,{region:c,orm:p,database:d,databaseHost:u,payment:A,paymentChoice:h,auth:g,socialLoginIds:E,aiProviders:S,deployTarget:m,docs:_,metering:H,billingMode:M,idp:he,accessGate:le,mcp:ee,waveToggles:$,previewSelections:K,config:C}=i,W={auth:g,payment:h,"billing-mode":M,idp:he,template:"saas","access-gate":le};l(s,{event:"step",step:"clone",status:"start"}),await Wo(t),l(s,{event:"step",step:"clone",status:"ok"}),l(s,{event:"step",step:"package",status:"start"}),await pr(t,n),l(s,{event:"step",step:"package",status:"ok"}),l(s,{event:"step",step:"config",status:"start"}),await _o(t,C),l(s,{event:"step",step:"config",status:"ok"}),l(s,{event:"step",step:"governance-lints",status:"start"});let de=await zo(t,C);l(s,{event:"step",step:"governance-lints",status:"ok",lints:de.lints}),l(s,{event:"step",step:"prune",status:"start"}),await br(t,C),l(s,{event:"step",step:"prune",status:"ok"});{let v=Xe.join(t,"packages/platform/db/prisma/schema.prisma"),R;try{R=Yt.readFileSync(v,"utf-8")}catch(w){if(Yr(w))l(s,{event:"step",step:"schema-prune",status:"skip"});else{let I=w instanceof Error?w.message:String(w);l(s,{event:"step",step:"schema-prune",status:"error",error:I})}}if(R!==void 0){l(s,{event:"step",step:"schema-prune",status:"start"});try{let w=wn(R,W);Yt.writeFileSync(v,w),Pn(Xe.join(Xe.dirname(v),"migrations"),W),l(s,{event:"step",step:"schema-prune",status:"ok"})}catch(w){let I=w instanceof Error?w.message:String(w);l(s,{event:"step",step:"schema-prune",status:"error",error:I})}}}if(l(s,{event:"step",step:"auth",choice:g,status:"start"}),await po(t,g),l(s,{event:"step",step:"auth",choice:g,status:"ok"}),E.length>0?(l(s,{event:"step",step:"social-login",providers:E,status:"start"}),await uo(t,E,g),l(s,{event:"step",step:"social-login",providers:E,status:"ok"})):l(s,{event:"step",step:"social-login",status:"skip"}),l(s,{event:"step",step:"db",choice:d,status:"start"}),await Ao(t,d,n),d!=="none"){let v=mt(u);v&&(await Co(t,v,n),l(s,{event:"step",step:"db-host",choice:u,status:"ok"}))}if(l(s,{event:"step",step:"db",choice:d,status:"ok"}),p==="drizzle"){l(s,{event:"step",step:"orm",choice:"drizzle",status:"start"});let v=await ur(t,"drizzle",d);l(s,{event:"step",step:"orm",choice:"drizzle",status:v.applied?"ok":"skip",...v.reason?{reason:v.reason}:{}})}if(l(s,{event:"step",step:"payment",choice:h,status:"start"}),await gr(t,h),l(s,{event:"step",step:"payment",choice:h,status:"ok"}),await Oo(t,i.email,c),s&&l(!0,{event:"step",step:"email",choice:i.email,status:"ok"}),await Br(t,i.storage,c),s&&l(!0,{event:"step",step:"storage",choice:i.storage,status:"ok"}),await ir(t,i.monitoring,c),s&&l(!0,{event:"step",step:"monitoring",choice:i.monitoring,status:"ok"}),await ao(t,i.analytics,c),s&&l(!0,{event:"step",step:"analytics",choice:i.analytics,status:"ok"}),await jr(t,i.sms,c),s&&l(!0,{event:"step",step:"sms",choice:i.sms,status:"ok"}),await xr(t,i.queue,c),s&&l(!0,{event:"step",step:"queue",choice:i.queue,status:"ok"}),await Dr(t,i.search,c),s&&l(!0,{event:"step",step:"search",choice:i.search,status:"ok"}),await yo(t,i.cache,c),s&&l(!0,{event:"step",step:"cache",choice:i.cache,status:"ok"}),await cr(t,i.notifications,c),s&&l(!0,{event:"step",step:"notifications",choice:i.notifications,status:"ok"}),await $r(t,i.webhooks,c),s&&l(!0,{event:"step",step:"webhooks",choice:i.webhooks,status:"ok"}),await vo(t,i.cms,c),s&&l(!0,{event:"step",step:"cms",choice:i.cms,status:"ok"}),await Vo(t,i.featureFlags,c),s&&l(!0,{event:"step",step:"feature-flags",choice:i.featureFlags,status:"ok"}),await ho(t,i.captcha,c),s&&l(!0,{event:"step",step:"captcha",choice:i.captcha,status:"ok"}),await tr(t,ee),s&&l(!0,{event:"step",step:"mcp",mode:ee,status:"ok"}),await or(t,H,A),s&&l(!0,{event:"step",step:"metering",mode:H,status:"ok"}),l(s,{event:"step",step:"prune-wave-features",status:"start"}),_r(t,$),l(s,{event:"step",step:"prune-wave-features",status:"ok",toggles:$}),C.orm==="prisma"&&C.database!=="none"?Jc(s,t,W):l(s,{event:"step",step:"schema-prune",status:"skip"}),l(s,{event:"step",step:"billing-mode",choice:M,status:"ok"}),l(s,{event:"step",step:"idp",choice:he,status:"ok"}),await bo(t,c),s&&l(!0,{event:"step",step:"compliance",region:c,status:"ok"}),await jo(t),await Mr(t,g),await Kr(t,{projectName:n,region:c,previewSelections:K,waveFeatures:$}),C.aiMode!=="none"){l(s,{event:"step",step:"ai-providers",status:"start"});let v={providerIds:C.aiProviders,customEndpoint:C.customAiEndpoint},R=Xe.join(t,"packages/ai/ai-providers/templates");await Er(t,v,R),l(s,{event:"step",step:"ai-providers",status:"ok"})}else l(s,{event:"step",step:"ai-providers",status:"skip"});l(s,{event:"step",step:"docs",status:"start"}),_!=="none"?(await Ro(t,{framework:_,projectName:n}),l(s,{event:"step",step:"docs",framework:"fumadocs",requested:_,status:"ok"})):l(s,{event:"step",step:"docs",status:"skip"}),l(s,{event:"step",step:"deploy-target",status:"start"}),m!=="none"&&await to(t,m),await eo(t,C.deployTargets),l(s,{event:"step",step:"deploy-target",status:"ok",targets:C.deployTargets});let P={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""};l(s,{event:"step",step:"env",status:"start"}),await Do(t,P),l(s,{event:"step",step:"env",status:"ok"}),l(s,{event:"step",step:"scaffold-extras",status:"start"});let Ee=await Tr(t,{projectName:n,withWorkflows:!!r.withWorkflows,withPythonBackend:!!r.withPythonBackend});l(s,{event:"step",step:"scaffold-extras",status:"ok",applied:Ee.applied,skipped:Ee.skipped}),l(s,{event:"step",step:"license",status:"start"});try{let v=er(t,{projectName:n,cliVersion:z});l(s,{event:"step",step:"license",status:"ok",tier:"mit-scaffold",wrote:v.wrote}),s||process.stdout.write(We.dim(` License: MIT \u2014 commercial use, closed source, no fee, no attribution.
2816
2816
  Upstream terms preserved as LICENSE-UPSTREAM-REFERENCE.md.
2817
- `))}catch(v){l(s,{event:"step",step:"license",status:"warn",message:v instanceof Error?v.message:String(v)})}if(r.install!==!1){let v=o==="bun"?"bun":o,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
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,R=["install"];s?l(!0,{event:"step",step:"install",pm:o,status:"start"}):process.stdout.write(We.dim(` Installing dependencies with ${o}\u2026
2818
+ `));try{Kt(v,R,{cwd:t,stdio:s?"ignore":"inherit"}),l(s,{event:"step",step:"install",status:"ok"}),s||process.stdout.write(We.green(` \u2713 Dependencies installed (${o})
2819
+ `))}catch(w){let I=w instanceof Error?w.message:String(w);s?l(!0,{event:"step",step:"install",status:"error",error:I}):process.stdout.write(We.yellow(`
2820
+ \u26A0 Install failed \u2014 the project files are ready, but deps are incomplete.
2821
+ Fix: ${We.cyan(`cd ${t} && ${o} install`)}
2822
2822
 
2823
- `))}var Qc=`Usage: create-sailor [name] [options]
2823
+ `))}}else l(s,{event:"step",step:"install",status:"skip"});if(r.git!==!1){s&&l(!0,{event:"step",step:"git-init",status:"start"});try{Kt("git",["init","-q"],{cwd:t,stdio:"ignore"}),Kt("git",["add","-A"],{cwd:t,stdio:"ignore"}),Kt("git",["-c","user.email=you@example.com","-c","user.name=You","commit","-q","-m","chore: initial scaffold from create-sailor"],{cwd:t,stdio:"ignore"}),l(s,{event:"step",step:"git-init",status:"ok"})}catch(v){let R=v instanceof Error?v.message:String(v);s?l(!0,{event:"step",step:"git-init",status:"error",error:R}):process.stdout.write(We.yellow(` \u26A0 git init skipped \u2014 not fatal.
2824
+ `))}}else l(s,{event:"step",step:"git-init",status:"skip"});let ve=Math.max(1,Math.round((Date.now()-a)/1e3));co({template_version:z,package_manager:o,region:c,auth:g,payment:h,ai_providers:S,deploy_target:m,duration_ms:Date.now()-a}),K.length>0&&zc(s,K),s?l(!0,{event:"done",status:"ok",elapsedSec:ve,targetDir:t,previewSelections:K,waveFeatures:$}):ro({elapsedSec:ve,targetDir:t,packageManager:o,skippedInstall:r.install===!1,hasDatabase:d!=="none",previewSelections:K});try{Xc({pkg:{name:"create-sailor",version:z},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}}import Qc from"cfonts";import Zc from"picocolors";function Gr(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${z}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
2825
+ `));return}Qc.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(Zc.dim(` AI-Native SaaS Template \xB7 v${z} \xB7 nebutra.com
2826
+
2827
+ `))}var ep=`Usage: create-sailor [name] [options]
2824
2828
 
2825
2829
  Arguments:
2826
2830
  name project name or path (default: my-app; use . for cwd)
@@ -2885,42 +2889,52 @@ Toggles:
2885
2889
  -h, --help show this help
2886
2890
  -v, --version show version
2887
2891
 
2892
+ Interactive flow:
2893
+ 1. Location \u2014 new folder (name) or current directory
2894
+ 2. Region / Auth / AI topology
2895
+ 3. Plan summary \u2014 confirm or customize payment \xB7 email \xB7 storage \xB7 deploy
2896
+ 4. Scaffold + golden-path next steps
2897
+
2888
2898
  Examples:
2889
2899
  $ npx create-sailor@latest
2890
2900
  $ npx create-sailor@latest my-app -y
2901
+ $ npx create-sailor@latest . --region=cn
2891
2902
  $ npx create-sailor@latest my-app --region=cn --auth=clerk
2892
2903
  $ npx create-sailor@latest my-app --region=hybrid --ai=openai,deepseek
2893
- $ npm create sailor@latest --dry-run --region=cn
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}
2904
+ $ npx create-sailor@latest my-app --dry-run --region=cn
2905
+ `;function Hr(){process.stdout.write(ep)}import qt from"picocolors";function Wr(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function tp(e){let t=Wr()?"\u25B8":"->",n=`[${e.index}/${e.total}]`,o=e.label.padEnd(18," ");return Wr()?`${qt.dim(n)} ${qt.bold(o)} ${qt.dim(t)} ${qt.cyan(e.value)}`:`${n} ${o} ${t} ${e.value}`}function Xr(e){process.stdout.write(tp(e)+`
2906
+ `)}import{existsSync as np,mkdirSync as op,writeFileSync as rp}from"fs";import{homedir as zr,platform as sp}from"os";import{join as wt}from"path";import In from"picocolors";function ip(){if(sp()==="win32"){let t=process.env.LOCALAPPDATA||wt(zr(),"AppData","Local");return wt(t,"nebutra")}let e=process.env.XDG_CONFIG_HOME;return e?wt(e,"nebutra"):wt(zr(),".config","nebutra")}function ap(){let e=process.env.NEBUTRA_TELEMETRY;return e==="0"||e==="false"||e==="no"}function Jr(e,t){try{op(e,{recursive:!0}),rp(t,"")}catch{}}function Qr(){if(!process.stderr.isTTY||!process.stdin.isTTY||process.env.CI)return;let e=ip(),t=wt(e,"first-run-acked");try{if(np(t))return}catch{return}if(ap()){Jr(e,t);return}let o=[`${In.cyan("\u2139")} Nebutra collects anonymous usage analytics to improve the scaffolder.`,` Opt out at any time: ${In.dim("export NEBUTRA_TELEMETRY=0")}`,` Privacy policy: ${In.dim("https://nebutra.com/legal/cli-analytics")}`,""];try{process.stderr.write(o.join(`
2907
+ `))}catch{}Jr(e,t)}import dt from"fs";import ye from"path";import*as D from"@clack/prompts";var Se="my-app",cp=new Set([".DS_Store",".Spotlight-V100",".Trashes","Thumbs.db","desktop.ini"]),Zr=new Set(["package.json","node_modules","pnpm-workspace.yaml","pnpm-lock.yaml","yarn.lock","package-lock.json","bun.lockb","turbo.json"]);function Tn(e){let t=e.trim();return t==="."||t==="./"||t===".\\"}function xn(e){if(!dt.existsSync(e))return!0;let t;try{t=dt.readdirSync(e)}catch{return!1}return t.every(n=>cp.has(n)||n===".git")}function Rn(e){if(!dt.existsSync(e))return!1;let t;try{t=dt.readdirSync(e)}catch{return!0}return t.some(n=>Zr.has(n))}function pp(e=process.cwd()){return xn(e)&&!Rn(e)}function es(e){let t=e.trim();if(!t)return"Please enter a project name.";if(t.length>128)return"Name is too long (max 128 characters).";if(!Tn(t)&&!(/[\\/]/.test(t)||ye.isAbsolute(t))&&!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(t))return"Use letters, numbers, dots, underscores, or hyphens (start with a letter or number)."}function lt(e,t=process.cwd()){let n=e.trim()||Se;if(Tn(n)){let a=ye.resolve(t);return{targetDir:".",projectName:ye.basename(a)||Se,absoluteDir:a}}if(ye.isAbsolute(n)||n.startsWith("./")||n.startsWith(".\\")||n.startsWith("../")||n.startsWith("..\\")||n.includes("/")||n.includes("\\")){let a=ye.resolve(t,n);return{targetDir:n,projectName:ye.basename(a)||Se,absoluteDir:a}}let r=es(n);if(r)throw new Error(r);let s=`./${n}`,i=ye.resolve(t,n);return{targetDir:s,projectName:n,absoluteDir:i}}async function ts(e={}){let t=e.cwd??process.cwd(),n=e.onCancel??(()=>{process.stdout.write(`Cancelled
2908
+ `),process.exit(130)}),o=pp(t),r=ye.basename(t)||t,s=await D.select({message:"Create the project\u2026",options:[{value:"new",label:"In a new folder",hint:o?void 0:"recommended from home or a parent directory"},{value:"current",label:"In the current directory",hint:o?`${r} looks empty \u2014 good to go`:t}],initialValue:o?"current":"new"});if(D.isCancel(s)&&n(),s==="current"){if(Rn(t)){let c=dt.readdirSync(t).filter(p=>Zr.has(p)).slice(0,4).join(", ");D.log.error(`Current directory already looks like a project (${c}). Choose a new folder, or pass a different path: create-sailor my-app`),n()}if(!xn(t)){let c=await D.confirm({message:"Current directory is not empty. Scaffold files will be mixed in \u2014 continue?",initialValue:!1});(D.isCancel(c)||!c)&&n()}return lt(".",t)}let i=await D.text({message:"What should we call your project?",placeholder:Se,defaultValue:Se,validate:c=>{let p=(c??"").trim()||Se;if(Tn(p)||/[\\/]/.test(p)||ye.isAbsolute(p))try{lt(p,t);return}catch(d){return d instanceof Error?d.message:"Invalid path."}return es(p)}});D.isCancel(i)&&n();let a=lt(String(i).trim()||Se,t);if(dt.existsSync(a.absoluteDir)&&!xn(a.absoluteDir)){Rn(a.absoluteDir)&&(D.log.error(`Folder "${a.projectName}" already exists and looks like a project. Pick another name.`),n());let c=await D.confirm({message:`Folder "${a.projectName}" is not empty. Continue?`,initialValue:!1});(D.isCancel(c)||!c)&&n()}return a}import*as j from"@clack/prompts";function lp(e){return{...e.config,region:e.region,orm:e.orm,database:e.database,databaseHost:e.databaseHost,payment:e.payment,aiMode:e.aiMode,aiRouting:e.aiRouting,aiProviders:e.aiProviders,customAiEndpoint:e.customAiEndpoint,deployTarget:e.deployTarget,deployTargets:e.deployTargets,docs:e.docs,i18n:e.i18n,email:e.email,storage:e.storage,monitoring:e.monitoring,analytics:e.analytics,sms:e.sms,queue:e.queue,search:e.search,cache:e.cache,notifications:e.notifications,webhooks:e.webhooks,cms:e.cms,featureFlags:e.featureFlags,captcha:e.captcha,mcp:e.mcp,metering:e.metering,billingMode:e.billingMode,idp:e.idp,accessGate:e.accessGate}}function dp(e){e.previewSelections=It([{flag:"queue",provider:e.queue},{flag:"search",provider:e.search},{flag:"notifications",provider:e.notifications},{flag:"webhooks",provider:e.webhooks},{flag:"feature-flags",provider:e.featureFlags},{flag:"captcha",provider:e.captcha},{flag:"access-gate",provider:e.accessGate}]),e.config=lp(e)}async function up(e,t){let n=await j.select({message:"Payment provider",options:[{value:"stripe",label:"Stripe",hint:"global default"},{value:"lemon",label:"Lemon Squeezy"},{value:"wechat",label:"WeChat Pay",hint:"CN"},{value:"alipay",label:"Alipay",hint:"CN"},{value:"none",label:"None"}],initialValue:e.paymentChoice});j.isCancel(n)&&t();let o=String(n);e.payment=gt(o),e.paymentChoice=ft(o);let r=await j.select({message:"Email provider",options:rt.map(a=>({value:a.id,label:a.name,hint:a.region==="cn"?"CN":a.id==="none"?void 0:"global"})),initialValue:e.email});j.isCancel(r)&&t(),e.email=String(r);let s=await j.select({message:"Object storage",options:Re.map(a=>({value:a.id,label:a.name,hint:a.region==="cn"?"CN":a.id==="none"?void 0:"global"})),initialValue:e.storage});j.isCancel(s)&&t(),e.storage=String(s);let i=await j.select({message:"Deploy target",options:[{value:"vercel",label:"Vercel",hint:"recommended for Next.js"},{value:"railway",label:"Railway"},{value:"cloudflare",label:"Cloudflare"},{value:"selfhost",label:"Self-host / Docker"}],initialValue:e.deployTarget});j.isCancel(i)&&t(),e.deployTarget=yt(String(i)),e.deployTargets=Ct(e.deployTarget),dp(e)}async function ns(e,t){let n={...e,config:{...e.config},aiProviders:[...e.aiProviders],socialLoginIds:[...e.socialLoginIds],previewSelections:[...e.previewSelections],deployTargets:{...e.deployTargets},waveToggles:{...e.waveToggles}},o=await j.select({message:"Create project with these settings?",options:[{value:"proceed",label:"Yes, create project",hint:"use region defaults above"},{value:"customize",label:"Customize key providers",hint:"payment \xB7 email \xB7 storage \xB7 deploy"},{value:"cancel",label:"Cancel"}],initialValue:"proceed"});return(j.isCancel(o)||o==="cancel")&&t(),o==="customize"&&(await up(n,t),j.log.success("Defaults updated \u2014 scaffolding with your choices.")),n}function xe(e,t){e&&process.stdout.write(JSON.stringify(t)+`
2909
+ `)}function gp(e,t,n,o,r){let{region:s,orm:i,database:a,paymentChoice:c,docs:p,socialLoginIds:d,aiMode:u,aiProviders:A,customAiEndpoint:h,deployTarget:g,metering:E,payment:S,billingMode:m,idp:_,mcp:H,waveToggles:M,previewSelections:he}=t,{email:le,storage:ee,monitoring:$,analytics:K,sms:C,queue:W,search:de,cache:P,notifications:Ee,webhooks:ze,cms:Je,featureFlags:ve,captcha:v}=t,R=A.length,w=[`clone template \u2192 ${n}`,"write nebutra.config.json",`governance-lints \u2192 write governance.config.json + wire pnpm lint (no-raw-inputs${a!=="none"?" + repository-seam":""})`,`prune template (orm=${i}, i18n=${t.i18n})`,`region \u2192 ${s}`,`auth \u2192 ${t.auth==="none"?"skip (remove packages/auth)":`configure ${t.auth}`}`,...d.length>0?[`social-login \u2192 generate ${d.length} callback route${d.length===1?"":"s"} + SocialLoginButtons.tsx (${d.join(", ")})`]:[],`db \u2192 ${a==="none"?"skip (remove packages/db)":`configure Prisma for ${a}`}`,...a!=="none"?[`db-host \u2192 configure ${t.databaseHost}`]:[],`payment \u2192 ${c==="none"?"skip (remove packages/billing)":`configure ${c}`}`,...p!=="none"?[`docs \u2192 scaffold apps/docs (${p==="fumadocs"?"fumadocs":`${p} \u2192 fumadocs fallback`})`]:[],...R>0||h?[`ai-providers \u2192 generate ${u} registry seed + env (${R}${h?" + custom":""} provider${R===1&&!h?"":"s"})`]:[],...le!=="none"?[`email \u2192 configure ${le}`]:[],...ee!=="none"?[`storage \u2192 configure ${ee}`]:[],...$!=="none"?[`monitoring \u2192 configure ${$}`]:[],...K!=="none"?[`analytics \u2192 configure ${K}`]:[],...C!=="none"?[`sms \u2192 configure ${C}`]:[],...W!=="none"?[`queue \u2192 configure ${W}`]:[],...de!=="none"?[`search \u2192 configure ${de}`]:[],...P!=="none"?[`cache \u2192 configure ${P}`]:[],...Ee!=="none"?[`notifications \u2192 configure ${Ee}`]:[],...ze!=="none"?[`webhooks \u2192 configure ${ze}`]:[],...Je!=="none"?[`cms \u2192 configure ${Je}`]:[],...ve!=="none"?[`feature-flags \u2192 configure ${ve}`]:[],...v!=="none"?[`captcha \u2192 configure ${v}`]:[],`mcp \u2192 ${H==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${E==="off"?"disabled":E==="auto"?S!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...m!=="usage"?[`billing-mode \u2192 ${m}`]:[],..._!=="clerk"?[`idp \u2192 ${_}`]:[],`cron-jobs \u2192 ${M.cronJobs?"enabled":"disabled"}`,`audit-log \u2192 ${M.auditLog?"enabled":"disabled"}`,`api-keys \u2192 ${M.apiKeys?"enabled":"disabled"}`,`command-palette \u2192 ${M.commandPalette?"enabled":"disabled"}`,`cookie-consent \u2192 ${M.cookieConsent?"enabled":"disabled"}`,`legal-pages \u2192 ${M.legalPages?"enabled":"disabled"}`,`china-compliance \u2192 ${M.chinaCompliance?"enabled (@nebutra/china-compliance + ICP footer)":"disabled"}`,`compliance \u2192 inject ${s} boilerplate (ICP/Cookie/AIGC/Privacy)`,"welcome \u2192 generate dev welcome page","env \u2192 generate random secrets (AUTH_SECRET, JWT_SECRET)","seed \u2192 generate prisma/seed.ts (1 admin + 3 tenants)",...g!=="none"?[`deploy \u2192 inject ${g} config`]:[],"inject .env.local",r.install===!1?"skip install":`run ${o} install`,r.git===!1?"skip git init":"run git init"];if(e){for(let I of w)xe(!0,{event:"plan",action:I});for(let I of he)xe(!0,{event:"warn",step:I.flag,provider:I.provider,packageStatus:I.status});xe(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
2910
+ `+L.bold(`Dry run \u2014 planned actions:
2911
+ `));for(let I of w)process.stdout.write(` \u2022 ${I}
2901
2912
  `);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(`
2913
+ `+L.bold(L.yellow(`Preview-status providers selected:
2914
+ `)));for(let I of he)process.stdout.write(L.yellow(`\u26A0 ${I.flag}=${I.provider}
2915
+ `))}process.stdout.write(L.dim(`
2905
2916
  No files were written.
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.
2917
+ `))}}async function fp(){let e=Bn();e.parse(process.argv);let t=e.opts(),[n]=e.args;t.help&&(Hr(),process.exit(0));let o=!!t.json,r=!!t.dryRun,i=!!t.yes||!process.stdin.isTTY;if(o||(Qr(),Gr()),xe(o,{event:"start",version:z}),!t.pm)try{mp("pnpm --version",{stdio:"ignore"})}catch{o||process.stderr.write(`
2918
+ ${L.red("\u2718")} ${L.bold("pnpm is required")} but was not found on PATH.
2908
2919
 
2909
2920
  The scaffold uses pnpm workspaces + Turborepo. Install pnpm first:
2910
- ${D.cyan("npm i -g pnpm@10")}
2911
-
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)
2914
-
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(`
2924
- \u2718 Failed: ${h}
2925
- `)),process.exit(1)}}cp().catch(e=>{process.stderr.write(String(e)+`
2921
+ ${L.cyan("npm i -g pnpm@10")}
2922
+
2923
+ Then retry: ${L.cyan("pnpm dlx create-sailor@latest")}
2924
+ (or pass ${L.dim("--pm=npm")} if you know workspace:* won't resolve in your setup)
2925
+
2926
+ `),xe(o,{event:"error",code:"PNPM_MISSING"}),process.exit(1)}let a=()=>{process.stdout.write(L.red(`\u2718 Cancelled
2927
+ `)),process.exit(130)},c,p;if(n)try{let g=lt(n);c=g.targetDir,p=g.projectName}catch(g){let E=g instanceof Error?g.message:String(g);process.stderr.write(`
2928
+ ${L.red("\u2718")} ${E}
2929
+
2930
+ `),xe(o,{event:"error",code:"INVALID_PROJECT_NAME",message:E}),process.exit(1)}else if(i){let g=lt(Se);c=g.targetDir,p=g.projectName}else{let g=await ts({onCancel:a});c=g.targetDir,p=g.projectName,o||process.stdout.write(L.dim(` \u2192 ${g.absoluteDir}
2931
+ `))}let d=t.pm??qn(),u=await oo(t,o),A=[["Project",p],["Region",u.region],["Auth",u.auth],["Payment",u.paymentChoice],["AI",`${u.aiMode}${u.aiProviders.length>0?` (${u.aiProviders.join(", ")})`:""}`],["Database",`${u.database} \xB7 ${u.databaseHost}`],["Email",u.email],["Storage",u.storage],["Deploy",u.deployTarget]];u.socialLoginIds.length>0&&A.push(["Social login",u.socialLoginIds.map(g=>Ze.find(E=>E.id===g)?.name??g).join(", ")]),o?A.forEach(([g,E],S)=>{xe(!0,{event:"step",step:g,value:E,index:S+1,total:A.length})}):(process.stdout.write(L.dim(`
2932
+ Plan
2933
+ `)),A.forEach(([g,E],S)=>{Xr({index:S+1,total:A.length,label:g,value:E})}),process.stdout.write(`
2934
+ `)),!i&&!o&&(u=await ns(u,a)),r&&(gp(o,u,c,d,t),process.exit(0));let h=async()=>{process.stdout.write(`
2935
+ `+L.red(`\u2718 Cancelled
2936
+ `)),os.existsSync(c)&&await rs.confirm({message:`Cleanup partial install at ${c}?`,initialValue:!0})===!0&&(os.rmSync(c,{recursive:!0,force:!0}),process.stdout.write(L.dim(` \u2713 Removed ${c}
2937
+ `))),process.exit(130)};process.on("SIGINT",h);try{await qr({resolvedTarget:c,projectName:p,resolvedPm:d,opts:t,useJson:o,resolved:u,startedAt:Date.now()}),process.exit(0)}catch(g){let E=g instanceof Error?g.message:String(g);o?xe(!0,{event:"error",message:E}):process.stdout.write(L.red(`
2938
+ \u2718 Failed: ${E}
2939
+ `)),process.exit(1)}}fp().catch(e=>{process.stderr.write(String(e)+`
2926
2940
  `),process.exit(1)});