create-sailor 1.8.0 → 1.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/aws-kms-3GX7ZOSJ.js +1 -0
- package/dist/{chunk-4AGDXYPL.js → chunk-5ECPN42W.js} +1 -1
- package/dist/chunk-FNDUJLS6.js +1 -0
- package/dist/chunk-HGJYEXMU.js +1 -0
- package/dist/chunk-HX3EZBGO.js +30 -0
- package/dist/chunk-IYWUY3VA.js +1 -0
- package/dist/chunk-JTXBZ2SU.js +1 -0
- package/dist/{chunk-M3QJPQWS.js → chunk-KRX2KWWT.js} +1 -1
- package/dist/chunk-OIQB5F6Y.js +1 -0
- package/dist/chunk-P2WEIQRQ.js +3 -0
- package/dist/chunk-RH2FFVSB.js +1 -0
- package/dist/chunk-STX7THHW.js +21 -0
- package/dist/chunk-TW5BOTVX.js +0 -0
- package/dist/chunk-VFREGXHN.js +1 -0
- package/dist/chunk-W5TBFCWY.js +4 -0
- package/dist/chunk-WJLTO7JW.js +0 -0
- package/dist/chunk-WU3IV4WF.js +1 -0
- package/dist/{chunk-UU4YUKYZ.js → chunk-XE3I3HCZ.js} +1 -1
- package/dist/chunk-ZIBRKYXP.js +23 -0
- package/dist/credits-HWAYRMKF.js +2635 -0
- package/dist/{dist-V6L2DNL2.js → dist-B346V4U6.js} +2 -2
- package/dist/dist-UXDXDLES.js +1 -0
- package/dist/dist-es-B5M7V6O6.js +1 -0
- package/dist/{dist-es-JATELSE4.js → dist-es-FU66ZQS5.js} +1 -1
- package/dist/dist-es-KE65J6GC.js +1 -0
- package/dist/dist-es-PFLN3FTL.js +5 -0
- package/dist/dist-es-U3NYQORW.js +1 -0
- package/dist/dist-es-VG3XXJ7M.js +2 -0
- package/dist/dist-es-WAHVDQ3F.js +2 -0
- package/dist/{event-streams-IPTOYMEP.js → event-streams-BXAP5G2H.js} +1 -1
- package/dist/event-streams-SGW54BDO.js +1 -0
- package/dist/index.js +184 -185
- package/dist/loadSso-WRXP2HXL.js +1 -0
- package/dist/local-6WWVOMA7.js +1 -0
- package/dist/{query_compiler_fast_bg.postgresql-FOSFFKA5.js → query_compiler_fast_bg.postgresql-JA2BFVW5.js} +1 -1
- package/dist/{query_compiler_fast_bg.postgresql.wasm-base64-JU7X67WB.js → query_compiler_fast_bg.postgresql.wasm-base64-URHQ2Y3Y.js} +1 -1
- package/dist/signin-JB7STGTR.js +1 -0
- package/dist/sso-oidc-LTNOJMPI.js +1 -0
- package/dist/sts-RKUL4Q47.js +5 -0
- package/package.json +1 -1
- package/templates/deploy/Dockerfile.web +1 -1
- package/dist/aws-kms-EYG3LGYA.js +0 -1
- package/dist/chunk-224RJRPV.js +0 -5
- package/dist/chunk-2YUF6TO6.js +0 -2
- package/dist/chunk-76FD5Z7D.js +0 -23
- package/dist/chunk-7OZT53MS.js +0 -1
- package/dist/chunk-AAIUIEEA.js +0 -1
- package/dist/chunk-C6CKWQY5.js +0 -20
- package/dist/chunk-CHWVD37K.js +0 -1
- package/dist/chunk-EBTFPGDR.js +0 -9
- package/dist/chunk-EIQ2HSZP.js +0 -1
- package/dist/chunk-FSRPMVAS.js +0 -1
- package/dist/chunk-IY2KKEUD.js +0 -1
- package/dist/chunk-OWZF7P72.js +0 -1
- package/dist/chunk-WI7DO2VU.js +0 -1
- package/dist/chunk-XPRSUMI6.js +0 -1
- package/dist/credits-7FJY7HK2.js +0 -2613
- package/dist/dist-LOLT3W3R.js +0 -1
- package/dist/dist-es-3AHFNYTD.js +0 -5
- package/dist/dist-es-6KZILXYZ.js +0 -1
- package/dist/dist-es-H627TNCU.js +0 -1
- package/dist/dist-es-I6TTSEP7.js +0 -2
- package/dist/dist-es-NRANDF25.js +0 -2
- package/dist/dist-es-YSAFQMS4.js +0 -1
- package/dist/loadSso-FR7LG5FX.js +0 -1
- package/dist/local-BUKM6VCO.js +0 -1
- package/dist/signin-N4XQB5ZB.js +0 -1
- package/dist/sso-oidc-FXPYRI5I.js +0 -1
- package/dist/sts-SIEJPPW3.js +0 -6
- /package/dist/{chunk-3T4EOSMQ.js → chunk-SPHQRDN5.js} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import"./chunk-FSRPMVAS.js";import{execSync as jc}from"child_process";import Vs from"fs";import Ks from"path";import*as nt from"@clack/prompts";import F from"picocolors";import{Command as Hs}from"commander";import In from"fs";import Vt from"path";import{fileURLToPath as qs}from"url";function Gs(){try{let t=Vt.dirname(qs(import.meta.url));for(let n=0;n<4;n++){let o=Vt.join(t,"package.json");if(In.existsSync(o)){let s=In.readFileSync(o,"utf-8"),r=JSON.parse(s);if(r.name==="create-sailor"&&typeof r.version=="string")return r.version}t=Vt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var X=Gs();var Ws="create-sailor";function Cn(){let e=new Hs;return e.name(Ws).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(X,"-v, --version").helpOption(!1).argument("[name]","project directory",void 0).option("-p, --pm <id>","npm | pnpm | yarn | bun").option("--region <id>","global | cn | hybrid").option("--orm <id>","prisma (default, primary) | drizzle (dual-ORM: adds db-drizzle alongside Prisma \u2014 Postgres only)").option("--db <id>","postgres | mysql | sqlite | none \u2014 engine (Prisma provider)").option("--db-host <id>","local | supabase | neon | vercel-postgres | planetscale | railway | aliyun-rds | tencent-cdb | none \u2014 managed-provider (region default: supabase global, local cn)").option("--auth <id>","clerk | betterauth | nextauth | supabase | none").option("--social-login <ids>","CN social login providers \u2014 wechat | qq | dingtalk | workweixin | feishu | weibo (comma-separated)").option("--payment <id>","stripe | lemon | wechat | alipay | none").option("--ai <mode-or-ids>","topology shorthand (gateway | direct | custom | none) OR comma-separated provider ids (e.g. openai,anthropic)").option("--deploy <target>","vercel | railway | cloudflare | selfhost").option("--docs <id>","fumadocs | mintlify | docusaurus | nextra | vitepress | none").option("--email <id>","resend | postmark | ses | aliyun-dm | tencent-ses | netease | none").option("--storage <id>","r2 | s3 | supabase-storage | aliyun-oss | tencent-cos | qiniu | none").option("--monitoring <id>","sentry | datadog | aliyun-arms | tingyun | none").option("--analytics <id>","posthog | plausible | umami | baidu | sensors | none").option("--sms <id>","twilio | aliyun-sms | tencent-sms | yunpian | none").option("--queue <id>","qstash | bullmq | sqs | none").option("--search <id>","meilisearch | typesense | algolia | pgvector | none").option("--cache <id>","upstash-redis | vercel-kv | redis | dragonfly | none").option("--notifications <id>","novu | knock | custom | none").option("--webhooks <id>","svix | custom | none").option("--cms <id>","sanity | contentful | strapi | none").option("--feature-flags <id>","vercel-flags | growthbook | configcat | none").option("--captcha <id>","turnstile | hcaptcha | aliyun-slide | none").option("--mcp <mode>","on | off (default: on)").option("--metering <mode>","auto | on | off (default: auto \u2014 auto-on when payment is set)").option("--billing-mode <mode>","usage | seat | credits (default: usage)").option("--idp <id>","clerk | oauth-server (default: clerk)").option("--access-gate <mode>","none | invite (default: none)").option("--cron-jobs <bool>","true | false \u2014 scaffold scheduled cron handlers (default: true)").option("--audit-log <bool>","true | false \u2014 enable /settings/audit-log + arch test (default: false \u2014 @nebutra/audit is WIP)").option("--api-keys <bool>","true | false \u2014 enable /settings/api-keys page (default: true)").option("--command-palette <bool>","true | false \u2014 enable \u2318K command palette (default: true)").option("--cookie-consent <bool>","true | false \u2014 enable GDPR/CCPA cookie banner (default: true)").option("--legal-pages <bool>","true | false \u2014 enable dynamic /legal/[slug] route (default: true)").option("--china-compliance <bool>","true | false \u2014 enable @nebutra/china-compliance + ICP footer (default: true when --region=cn, otherwise false)").option("--i18n","enable i18n").option("--no-i18n","disable i18n").option("--with-workflows","scaffold workflows/ (inngest + n8n + pusher stubs)").option("--with-python-backend","scaffold backends/python/ (FastAPI stub \u2014 only when TS-by-Default ADR exception applies)").option("--no-install","skip package install").option("--no-git","skip git init").option("-y, --yes","accept all defaults (non-interactive)").option("--dry-run","preview actions without writing files").option("--json","machine-readable output").option("--no-color","disable color output").option("-h, --help","show help"),e}import kn from"picocolors";var Kt=[{id:"local",name:"Local / Self-hosted Docker",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres:postgres@localhost:5432/$PROJECT",comment:"Local Postgres via docker-compose (pnpm infra:up)"}],docs:"https://www.postgresql.org/docs/",description:"Docker on localhost. You operate it.",tier:"self-hosted"},{id:"supabase",name:"Supabase",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:5432/postgres?sslmode=require",comment:"Supabase session pooler \u2014 use for runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://postgres:<password>@db.<project-ref>.supabase.co:5432/postgres?sslmode=require",comment:"Supabase direct \u2014 use for Prisma migrations"},{name:"NEXT_PUBLIC_SUPABASE_URL",placeholder:"https://<project>.supabase.co"},{name:"NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY",placeholder:""},{name:"NEXT_PUBLIC_SUPABASE_ANON_KEY",placeholder:""},{name:"SUPABASE_PUBLISHABLE_KEY",placeholder:""},{name:"SUPABASE_SERVICE_ROLE_KEY",placeholder:""}],docs:"https://supabase.com/docs",description:"Managed Postgres + auth/storage/realtime/edge-functions.",tier:"managed"},{id:"neon",name:"Neon",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>-pooler.<region>.neon.tech/<db>?sslmode=require",comment:"Neon pooled \u2014 runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>.<region>.neon.tech/<db>?sslmode=require",comment:"Neon direct (no -pooler) \u2014 migrations"}],docs:"https://neon.tech/docs",description:"Serverless Postgres with branching and scale-to-zero.",tier:"managed"},{id:"vercel-postgres",name:"Vercel Postgres",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"$POSTGRES_PRISMA_URL",comment:"Vercel Marketplace injects POSTGRES_PRISMA_URL automatically"},{name:"DIRECT_URL",placeholder:"$POSTGRES_URL_NON_POOLING",comment:"Vercel Marketplace injects POSTGRES_URL_NON_POOLING automatically"}],docs:"https://vercel.com/docs/storage/vercel-postgres",description:"Neon-backed, auto-provisioned via Vercel Marketplace.",tier:"managed"},{id:"planetscale",name:"PlanetScale",region:"global",supportedEngines:["mysql"],forcedEngine:"mysql",prismaDatasourceExtras:['relationMode = "prisma"'],envVars:[{name:"DATABASE_URL",placeholder:"mysql://<user>:<pass>@<host>.psdb.cloud/<db>?sslaccept=strict",comment:'PlanetScale: relationMode = "prisma" (no FK support server-side)'}],docs:"https://planetscale.com/docs",description:"Managed MySQL with branching. No foreign keys.",tier:"managed"},{id:"railway",name:"Railway",region:"global",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"$DATABASE_URL",comment:"Railway service env var; injected when you link a Postgres service"}],docs:"https://docs.railway.app/databases/postgresql",description:"Generalist managed infra; standard TCP Postgres/MySQL.",tier:"managed"},{id:"aliyun-rds",name:"Aliyun RDS",region:"cn",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@<rds-instance>.rds.aliyuncs.com:5432/<db>",comment:"Aliyun RDS Postgres \u2014 internal VPC endpoint recommended"}],docs:"https://www.alibabacloud.com/help/en/rds",description:"Aliyun RDS \u2014 China compliance + intranet routing.",tier:"managed"},{id:"tencent-cdb",name:"Tencent CloudDB (CDB)",region:"cn",supportedEngines:["mysql","postgresql"],envVars:[{name:"DATABASE_URL",placeholder:"mysql://<user>:<pwd>@<cdb-instance>.tencentcdb.com:3306/<db>",comment:"Tencent CloudDB \u2014 VPC endpoint recommended"}],docs:"https://intl.cloud.tencent.com/document/product/236",description:"Tencent CloudDB \u2014 China compliance.",tier:"managed"},{id:"none",name:"None",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[],docs:"",description:"Skip database scaffolding.",tier:"self-hosted"}];function st(e){return Kt.find(t=>t.id===e)}function xn(e){return e==="cn"||e==="hybrid"?"local":"supabase"}var rt=[{id:"r2",name:"Cloudflare R2",region:"global",envVars:["R2_ACCOUNT_ID","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY","R2_BUCKET"],docs:"https://developers.cloudflare.com/r2/api/s3/api/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"s3",name:"AWS S3",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_S3_REGION","S3_BUCKET"],docs:"https://docs.aws.amazon.com/s3/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"supabase-storage",name:"Supabase Storage",region:"global",envVars:["SUPABASE_URL","SUPABASE_SERVICE_ROLE_KEY","SUPABASE_BUCKET"],docs:"https://supabase.com/docs/guides/storage",pkg:"@supabase/supabase-js",pkgVersion:"^2.45.4"},{id:"aliyun-oss",name:"\u963F\u91CC\u4E91 OSS",region:"cn",envVars:["ALIYUN_OSS_ACCESS_KEY","ALIYUN_OSS_ACCESS_SECRET","ALIYUN_OSS_REGION","ALIYUN_OSS_BUCKET"],docs:"https://help.aliyun.com/product/31815.html",pkg:"ali-oss",pkgVersion:"^6.21.0"},{id:"tencent-cos",name:"\u817E\u8BAF\u4E91 COS",region:"cn",envVars:["TENCENT_COS_SECRET_ID","TENCENT_COS_SECRET_KEY","TENCENT_COS_BUCKET","TENCENT_COS_REGION"],docs:"https://cloud.tencent.com/document/product/436",pkg:"cos-nodejs-sdk-v5",pkgVersion:"^2.13.7"},{id:"qiniu",name:"\u4E03\u725B\u4E91 Kodo",region:"cn",envVars:["QINIU_ACCESS_KEY","QINIU_SECRET_KEY","QINIU_BUCKET","QINIU_DOMAIN"],docs:"https://developer.qiniu.com/kodo",pkg:"qiniu",pkgVersion:"^7.14.0"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function $t(e){let t=e==="supabase"?"supabase-storage":e;return rt.some(n=>n.id===t)?t:void 0}function Rn(e){let t=$t(e);return t?rt.find(n=>n.id===t):void 0}var zc=rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Nn(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function Yt(e){switch(e){case"postgres":case"postgresql":return"postgresql";case"mysql":return"mysql";case"sqlite":return"sqlite";case"none":return"none";default:return"postgresql"}}function qt(e,t,n){let o=e?.trim().toLowerCase()??xn(t),s=st(o);if(!s){let i=Kt.map(a=>a.id).join(", ");throw new Error(`Unknown --db-host="${o}". Valid: ${i}`)}let r=n;return s.forcedEngine&&r!=="none"&&r!==s.forcedEngine&&(r=s.forcedEngine),{hostId:s.id,engine:r}}function Gt(e){return e==="drizzle"?"drizzle":"prisma"}function Ht(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function Wt(e){if(!e)return"stripe";let t=e.toLowerCase();return t==="lemon"||t==="lemonsqueezy"?"lemon":t==="wechat"?"wechat":t==="alipay"?"alipay":t==="none"?"none":"stripe"}function Xt(e){if(!e)return"clerk";let t=e.toLowerCase();return t==="betterauth"||t==="better-auth"?"betterauth":t==="nextauth"||t==="next-auth"||t==="authjs"||t==="auth.js"?"nextauth":t==="supabase"||t==="supabase-auth"?"supabase":t==="none"?"none":"clerk"}var Xs=new Set(["gateway","direct","custom","none"]);function zt(e){if(!e)return!1;let t=e.trim().toLowerCase();return Xs.has(t)}function Jt(e){if(!e)return["openai"];if(zt(e))return[];let t=e.split(",").map(n=>n.trim().toLowerCase());return t.includes("none")?[]:t}function On(e,t){let n=e??t;return $t(n)??n}var Tn={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function Qt(e,t){if(!e)return"fumadocs";let n=e.toLowerCase();if(n==="fumadocs"||n==="none")return n;if(n in Tn){let o=Tn[n];return t?process.stdout.write(JSON.stringify({event:"notice",kind:"docs-fallback",requested:n,effective:"fumadocs"})+`
|
|
2
|
+
import"./chunk-IYWUY3VA.js";import{execSync as Vc}from"child_process";import Vr from"fs";import Kr from"path";import*as ot from"@clack/prompts";import F from"picocolors";import{Command as Hr}from"commander";import In from"fs";import Vt from"path";import{fileURLToPath as qr}from"url";function Gr(){try{let t=Vt.dirname(qr(import.meta.url));for(let n=0;n<4;n++){let o=Vt.join(t,"package.json");if(In.existsSync(o)){let r=In.readFileSync(o,"utf-8"),s=JSON.parse(r);if(s.name==="create-sailor"&&typeof s.version=="string")return s.version}t=Vt.dirname(t)}return"0.0.0-dev"}catch{return"0.0.0-dev"}}var X=Gr();var Wr="create-sailor";function Cn(){let e=new Hr;return e.name(Wr).description("Nebutra-Sailor \u2014 AI-Native SaaS template").version(X,"-v, --version").helpOption(!1).argument("[name]","project directory",void 0).option("-p, --pm <id>","npm | pnpm | yarn | bun").option("--region <id>","global | cn | hybrid").option("--orm <id>","prisma (default, primary) | drizzle (dual-ORM: adds db-drizzle alongside Prisma \u2014 Postgres only)").option("--db <id>","postgres | mysql | sqlite | none \u2014 engine (Prisma provider)").option("--db-host <id>","local | supabase | neon | vercel-postgres | planetscale | railway | aliyun-rds | tencent-cdb | none \u2014 managed-provider (region default: supabase global, local cn)").option("--auth <id>","clerk | betterauth | nextauth | supabase | none").option("--social-login <ids>","CN social login providers \u2014 wechat | qq | dingtalk | workweixin | feishu | weibo (comma-separated)").option("--payment <id>","stripe | lemon | wechat | alipay | none").option("--ai <mode-or-ids>","topology shorthand (gateway | direct | custom | none) OR comma-separated provider ids (e.g. openai,anthropic)").option("--deploy <target>","vercel | railway | cloudflare | selfhost").option("--docs <id>","fumadocs | mintlify | docusaurus | nextra | vitepress | none").option("--email <id>","resend | postmark | ses | aliyun-dm | tencent-ses | netease | none").option("--storage <id>","r2 | s3 | supabase-storage | aliyun-oss | tencent-cos | qiniu | none").option("--monitoring <id>","sentry | datadog | aliyun-arms | tingyun | none").option("--analytics <id>","posthog | plausible | umami | baidu | sensors | none").option("--sms <id>","twilio | aliyun-sms | tencent-sms | yunpian | none").option("--queue <id>","qstash | bullmq | sqs | none").option("--search <id>","meilisearch | typesense | algolia | pgvector | none").option("--cache <id>","upstash-redis | vercel-kv | redis | dragonfly | none").option("--notifications <id>","novu | knock | custom | none").option("--webhooks <id>","svix | custom | none").option("--cms <id>","sanity | contentful | strapi | none").option("--feature-flags <id>","vercel-flags | growthbook | configcat | none").option("--captcha <id>","turnstile | hcaptcha | aliyun-slide | none").option("--mcp <mode>","on | off (default: on)").option("--metering <mode>","auto | on | off (default: auto \u2014 auto-on when payment is set)").option("--billing-mode <mode>","usage | seat | credits (default: usage)").option("--idp <id>","clerk | oauth-server (default: clerk)").option("--access-gate <mode>","none | invite (default: none)").option("--cron-jobs <bool>","true | false \u2014 scaffold scheduled cron handlers (default: true)").option("--audit-log <bool>","true | false \u2014 enable /settings/audit-log + arch test (default: false \u2014 @nebutra/audit is WIP)").option("--api-keys <bool>","true | false \u2014 enable /settings/api-keys page (default: true)").option("--command-palette <bool>","true | false \u2014 enable \u2318K command palette (default: true)").option("--cookie-consent <bool>","true | false \u2014 enable GDPR/CCPA cookie banner (default: true)").option("--legal-pages <bool>","true | false \u2014 enable dynamic /legal/[slug] route (default: true)").option("--china-compliance <bool>","true | false \u2014 enable @nebutra/china-compliance + ICP footer (default: true when --region=cn, otherwise false)").option("--i18n","enable i18n").option("--no-i18n","disable i18n").option("--with-workflows","scaffold workflows/ (inngest + n8n + pusher stubs)").option("--with-python-backend","scaffold backends/python/ (FastAPI stub \u2014 only when TS-by-Default ADR exception applies)").option("--no-install","skip package install").option("--no-git","skip git init").option("-y, --yes","accept all defaults (non-interactive)").option("--dry-run","preview actions without writing files").option("--json","machine-readable output").option("--no-color","disable color output").option("-h, --help","show help"),e}import kn from"picocolors";var Kt=[{id:"local",name:"Local / Self-hosted Docker",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres:postgres@localhost:5432/$PROJECT",comment:"Local Postgres via docker-compose (pnpm infra:up)"}],docs:"https://www.postgresql.org/docs/",description:"Docker on localhost. You operate it.",tier:"self-hosted"},{id:"supabase",name:"Supabase",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:5432/postgres?sslmode=require",comment:"Supabase session pooler \u2014 use for runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://postgres:<password>@db.<project-ref>.supabase.co:5432/postgres?sslmode=require",comment:"Supabase direct \u2014 use for Prisma migrations"},{name:"NEXT_PUBLIC_SUPABASE_URL",placeholder:"https://<project>.supabase.co"},{name:"NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY",placeholder:""},{name:"NEXT_PUBLIC_SUPABASE_ANON_KEY",placeholder:""},{name:"SUPABASE_PUBLISHABLE_KEY",placeholder:""},{name:"SUPABASE_SERVICE_ROLE_KEY",placeholder:""}],docs:"https://supabase.com/docs",description:"Managed Postgres + auth/storage/realtime/edge-functions.",tier:"managed"},{id:"neon",name:"Neon",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>-pooler.<region>.neon.tech/<db>?sslmode=require",comment:"Neon pooled \u2014 runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://<user>:<pwd>@ep-<branch>.<region>.neon.tech/<db>?sslmode=require",comment:"Neon direct (no -pooler) \u2014 migrations"}],docs:"https://neon.tech/docs",description:"Serverless Postgres with branching and scale-to-zero.",tier:"managed"},{id:"vercel-postgres",name:"Vercel Postgres",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"$POSTGRES_PRISMA_URL",comment:"Vercel Marketplace injects POSTGRES_PRISMA_URL automatically"},{name:"DIRECT_URL",placeholder:"$POSTGRES_URL_NON_POOLING",comment:"Vercel Marketplace injects POSTGRES_URL_NON_POOLING automatically"}],docs:"https://vercel.com/docs/storage/vercel-postgres",description:"Neon-backed, auto-provisioned via Vercel Marketplace.",tier:"managed"},{id:"planetscale",name:"PlanetScale Postgres",region:"global",supportedEngines:["postgresql"],forcedEngine:"postgresql",keepDirectUrl:!0,envVars:[{name:"DATABASE_URL",placeholder:"postgresql://postgres.<branch-id>:<password>@<host>.horizon.psdb.cloud:6432/postgres?sslmode=require",comment:"PlanetScale Postgres pooled/PgBouncer URL \u2014 runtime queries"},{name:"DIRECT_URL",placeholder:"postgresql://postgres.<branch-id>:<password>@<host>.horizon.psdb.cloud:5432/postgres?sslmode=require",comment:"PlanetScale Postgres direct URL \u2014 Prisma migrations"}],docs:"https://planetscale.com/docs/postgres",description:"Managed Postgres with branching; compatible with Sailor migrations.",tier:"managed"},{id:"railway",name:"Railway",region:"global",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"$DATABASE_URL",comment:"Railway service env var; injected when you link a Postgres service"}],docs:"https://docs.railway.app/databases/postgresql",description:"Generalist managed infra; standard TCP Postgres/MySQL.",tier:"managed"},{id:"aliyun-rds",name:"Aliyun RDS",region:"cn",supportedEngines:["postgresql","mysql"],envVars:[{name:"DATABASE_URL",placeholder:"postgresql://<user>:<pwd>@<rds-instance>.rds.aliyuncs.com:5432/<db>",comment:"Aliyun RDS Postgres \u2014 internal VPC endpoint recommended"}],docs:"https://www.alibabacloud.com/help/en/rds",description:"Aliyun RDS \u2014 China compliance + intranet routing.",tier:"managed"},{id:"tencent-cdb",name:"Tencent CloudDB (CDB)",region:"cn",supportedEngines:["mysql","postgresql"],envVars:[{name:"DATABASE_URL",placeholder:"mysql://<user>:<pwd>@<cdb-instance>.tencentcdb.com:3306/<db>",comment:"Tencent CloudDB \u2014 VPC endpoint recommended"}],docs:"https://intl.cloud.tencent.com/document/product/236",description:"Tencent CloudDB \u2014 China compliance.",tier:"managed"},{id:"none",name:"None",region:"both",supportedEngines:["postgresql","mysql","sqlite"],envVars:[],docs:"",description:"Skip database scaffolding.",tier:"self-hosted"}];function st(e){return Kt.find(t=>t.id===e)}function xn(e){return e==="cn"||e==="hybrid"?"local":"supabase"}var it=[{id:"r2",name:"Cloudflare R2",region:"global",envVars:["R2_ACCOUNT_ID","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY","R2_BUCKET"],docs:"https://developers.cloudflare.com/r2/api/s3/api/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"s3",name:"AWS S3",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_S3_REGION","S3_BUCKET"],docs:"https://docs.aws.amazon.com/s3/",pkg:"@aws-sdk/client-s3",pkgVersion:"^3.658.0"},{id:"supabase-storage",name:"Supabase Storage",region:"global",envVars:["SUPABASE_URL","SUPABASE_SERVICE_ROLE_KEY","SUPABASE_BUCKET"],docs:"https://supabase.com/docs/guides/storage",pkg:"@supabase/supabase-js",pkgVersion:"^2.45.4"},{id:"aliyun-oss",name:"\u963F\u91CC\u4E91 OSS",region:"cn",envVars:["ALIYUN_OSS_ACCESS_KEY","ALIYUN_OSS_ACCESS_SECRET","ALIYUN_OSS_REGION","ALIYUN_OSS_BUCKET"],docs:"https://help.aliyun.com/product/31815.html",pkg:"ali-oss",pkgVersion:"^6.21.0"},{id:"tencent-cos",name:"\u817E\u8BAF\u4E91 COS",region:"cn",envVars:["TENCENT_COS_SECRET_ID","TENCENT_COS_SECRET_KEY","TENCENT_COS_BUCKET","TENCENT_COS_REGION"],docs:"https://cloud.tencent.com/document/product/436",pkg:"cos-nodejs-sdk-v5",pkgVersion:"^2.13.7"},{id:"qiniu",name:"\u4E03\u725B\u4E91 Kodo",region:"cn",envVars:["QINIU_ACCESS_KEY","QINIU_SECRET_KEY","QINIU_BUCKET","QINIU_DOMAIN"],docs:"https://developer.qiniu.com/kodo",pkg:"qiniu",pkgVersion:"^7.14.0"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function $t(e){let t=e==="supabase"?"supabase-storage":e;return it.some(n=>n.id===t)?t:void 0}function Rn(e){let t=$t(e);return t?it.find(n=>n.id===t):void 0}var Qc=it.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Nn(){let e=process.env.npm_config_user_agent??"";return e.startsWith("pnpm")?"pnpm":e.startsWith("yarn")?"yarn":e.startsWith("bun")?"bun":"npm"}function Yt(e){switch(e){case"postgres":case"postgresql":return"postgresql";case"mysql":return"mysql";case"sqlite":return"sqlite";case"none":return"none";default:return"postgresql"}}function qt(e,t,n){let o=e?.trim().toLowerCase()??xn(t),r=st(o);if(!r){let i=Kt.map(a=>a.id).join(", ");throw new Error(`Unknown --db-host="${o}". Valid: ${i}`)}let s=n;return r.forcedEngine&&s!=="none"&&s!==r.forcedEngine&&(s=r.forcedEngine),{hostId:r.id,engine:s}}function Gt(e){return e==="drizzle"?"drizzle":"prisma"}function Ht(e){return e==="lemon"||e==="lemonsqueezy"?"lemon":e==="wechat"?"wechat":e==="alipay"?"alipay":e==="none"?"none":"stripe"}function Wt(e){if(!e)return"stripe";let t=e.toLowerCase();return t==="lemon"||t==="lemonsqueezy"?"lemon":t==="wechat"?"wechat":t==="alipay"?"alipay":t==="none"?"none":"stripe"}function Xt(e){if(!e)return"clerk";let t=e.toLowerCase();return t==="betterauth"||t==="better-auth"?"betterauth":t==="nextauth"||t==="next-auth"||t==="authjs"||t==="auth.js"?"nextauth":t==="supabase"||t==="supabase-auth"?"supabase":t==="none"?"none":"clerk"}var Xr=new Set(["gateway","direct","custom","none"]);function zt(e){if(!e)return!1;let t=e.trim().toLowerCase();return Xr.has(t)}function Jt(e){if(!e)return["openai"];if(zt(e))return[];let t=e.split(",").map(n=>n.trim().toLowerCase());return t.includes("none")?[]:t}function On(e,t){let n=e??t;return $t(n)??n}var Tn={mintlify:"Mintlify",docusaurus:"Docusaurus",nextra:"Nextra",vitepress:"VitePress"};function Qt(e,t){if(!e)return"fumadocs";let n=e.toLowerCase();if(n==="fumadocs"||n==="none")return n;if(n in Tn){let o=Tn[n];return t?process.stdout.write(JSON.stringify({event:"notice",kind:"docs-fallback",requested:n,effective:"fumadocs"})+`
|
|
3
3
|
`):process.stdout.write(kn.yellow(`\u26A0 ${o} support is coming in v1.2. Falling back to fumadocs.
|
|
4
4
|
`)+kn.dim(` Track progress: https://github.com/Nebutra/Nebutra-Sailor/issues
|
|
5
|
-
`)),"fumadocs"}return"fumadocs"}function Zt(e){switch(e){case"vercel":return"vercel";case"railway":return"railway";case"cloudflare":return"cloudflare";case"selfhost":return"selfhost";case"none":return"none";default:return"vercel"}}function en(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function Ln(e){return{...e==="cn"?{email:"aliyun-dm",storage:"aliyun-oss",monitoring:"sentry",analytics:"baidu",sms:"aliyun-sms"}:e==="hybrid"?{email:"resend",storage:"aliyun-oss",monitoring:"sentry",analytics:"posthog",sms:"aliyun-sms"}:{email:"resend",storage:"r2",monitoring:"sentry",analytics:"posthog",sms:"twilio"},queue:"none",search:"none",cache:e==="global"?"upstash-redis":e==="cn"?"redis":"upstash-redis",notifications:"none",webhooks:"none",cms:"none",featureFlags:"none",captcha:"none",mcp:"on",metering:"auto",billingMode:"usage",idp:"clerk",accessGate:"none"}}function tn(e){return e==="cn"?"wechat":"stripe"}import*as Y from"@clack/prompts";import ir from"picocolors";var nn=[{id:"anthropic",name:"Anthropic",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://docs.anthropic.com",envVarPrefix:"ANTHROPIC",requiredEnvVars:["ANTHROPIC_API_KEY"]},{id:"openai",name:"OpenAI",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.openai.com/docs",envVarPrefix:"OPENAI",requiredEnvVars:["OPENAI_API_KEY"]},{id:"deepseek",name:"DeepSeek",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.deepseek.com/api-docs",envVarPrefix:"DEEPSEEK",requiredEnvVars:["DEEPSEEK_API_KEY"]},{id:"xai",name:"xAI (Grok)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://docs.x.ai/api",envVarPrefix:"XAI",requiredEnvVars:["XAI_API_KEY"]},{id:"moonshot",name:"Moonshot (Kimi)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.moonshot.cn/docs",envVarPrefix:"MOONSHOT",requiredEnvVars:["MOONSHOT_API_KEY","MOONSHOT_BASE_URL"]},{id:"google",name:"Google Gemini",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://ai.google.dev/gemini-api/docs",envVarPrefix:"GOOGLE_GENERATIVE_AI",requiredEnvVars:["GOOGLE_GENERATIVE_AI_API_KEY"]},{id:"mistral",name:"Mistral AI",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://docs.mistral.ai",envVarPrefix:"MISTRAL",requiredEnvVars:["MISTRAL_API_KEY"]},{id:"cohere",name:"Cohere",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://docs.cohere.com",envVarPrefix:"COHERE",requiredEnvVars:["COHERE_API_KEY"]},{id:"perplexity",name:"Perplexity",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://docs.perplexity.ai",baseURL:"https://api.perplexity.ai",envVarPrefix:"PERPLEXITY",requiredEnvVars:["PERPLEXITY_API_KEY"]},{id:"ai21",name:"AI21 Labs",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://docs.ai21.com",baseURL:"https://api.ai21.com/studio/v1",envVarPrefix:"AI21",requiredEnvVars:["AI21_API_KEY"]},{id:"upstage",name:"Upstage (Solar)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://developers.upstage.ai/docs",baseURL:"https://api.upstage.ai/v1/solar",envVarPrefix:"UPSTAGE",requiredEnvVars:["UPSTAGE_API_KEY"]},{id:"siliconflow",name:"\u7845\u57FA\u6D41\u52A8 SiliconFlow",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://docs.siliconflow.cn",baseURL:"https://api.siliconflow.cn/v1",envVarPrefix:"SILICONFLOW",requiredEnvVars:["SILICONFLOW_API_KEY"]},{id:"volcengine-ark",name:"\u706B\u5C71\u5F15\u64CE ARK (\u8C46\u5305)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://www.volcengine.com/docs/82379",baseURL:"https://ark.cn-beijing.volces.com/api/v3",envVarPrefix:"ARK",requiredEnvVars:["ARK_API_KEY"]},{id:"bailian",name:"\u767E\u70BC Bailian (\u901A\u4E49)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://help.aliyun.com/zh/model-studio",baseURL:"https://dashscope.aliyuncs.com/compatible-mode/v1",envVarPrefix:"DASHSCOPE",requiredEnvVars:["DASHSCOPE_API_KEY"]},{id:"zhipu",name:"\u667A\u8C31 AI Zhipu",category:"\u56FD\u5185\u5E73\u53F0",status:"ai-sdk",docs:"https://docs.bigmodel.cn",baseURL:"https://open.bigmodel.cn/api/paas/v4",envVarPrefix:"ZHIPU",requiredEnvVars:["ZHIPU_API_KEY"]},{id:"baichuan",name:"\u767E\u5DDD\u667A\u80FD Baichuan",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.baichuan-ai.com/docs",baseURL:"https://api.baichuan-ai.com/v1",envVarPrefix:"BAICHUAN",requiredEnvVars:["BAICHUAN_API_KEY"]},{id:"minimax",name:"MiniMax (ABAB)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.minimaxi.com/document/guides",baseURL:"https://api.minimax.chat/v1",envVarPrefix:"MINIMAX",requiredEnvVars:["MINIMAX_API_KEY","MINIMAX_GROUP_ID"]},{id:"stepfun",name:"\u9636\u8DC3\u661F\u8FB0 StepFun",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.stepfun.com/docs",baseURL:"https://api.stepfun.com/v1",envVarPrefix:"STEPFUN",requiredEnvVars:["STEPFUN_API_KEY"]},{id:"sensetime",name:"\u5546\u6C64 SenseNova",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.sensetime.com",baseURL:"https://api.sensenova.cn/v1",envVarPrefix:"SENSENOVA",requiredEnvVars:["SENSENOVA_API_KEY"]},{id:"tencent",name:"\u817E\u8BAF\u6DF7\u5143 Hunyuan",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://cloud.tencent.com/document/product/1729",baseURL:"https://api.hunyuan.cloud.tencent.com/v1",envVarPrefix:"HUNYUAN",requiredEnvVars:["HUNYUAN_API_KEY"]},{id:"lingyi",name:"\u96F6\u4E00\u4E07\u7269 Yi",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.lingyiwanwu.com/docs",baseURL:"https://api.lingyiwanwu.com/v1",envVarPrefix:"YI",requiredEnvVars:["YI_API_KEY"]},{id:"openrouter",name:"OpenRouter",category:"\u7EDF\u4E00\u7F51\u5173",status:"opencode",docs:"https://openrouter.ai/docs",envVarPrefix:"OPENROUTER",requiredEnvVars:["OPENROUTER_API_KEY"]},{id:"vercel-gateway",name:"Vercel AI Gateway",category:"\u7EDF\u4E00\u7F51\u5173",status:"opencode",docs:"https://vercel.com/docs/ai-gateway",envVarPrefix:"AI_GATEWAY",requiredEnvVars:["AI_GATEWAY_API_KEY"]},{id:"litellm",name:"LiteLLM Proxy",category:"\u7EDF\u4E00\u7F51\u5173",status:"cn-compatible",docs:"https://docs.litellm.ai",baseURL:"http://localhost:4000/v1",envVarPrefix:"LITELLM",requiredEnvVars:["LITELLM_API_KEY"]},{id:"portkey",name:"Portkey",category:"\u7EDF\u4E00\u7F51\u5173",status:"cn-compatible",docs:"https://portkey.ai/docs",baseURL:"https://api.portkey.ai/v1",envVarPrefix:"PORTKEY",requiredEnvVars:["PORTKEY_API_KEY"]},{id:"aws-bedrock",name:"AWS Bedrock",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://aws.amazon.com/bedrock/",envVarPrefix:"AWS_BEDROCK",requiredEnvVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_REGION"]},{id:"azure-openai",name:"Azure OpenAI",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://azure.microsoft.com/en-us/products/cognitive-services/openai-service/",envVarPrefix:"AZURE_OPENAI",requiredEnvVars:["AZURE_OPENAI_API_KEY","AZURE_OPENAI_ENDPOINT"]},{id:"gcp-vertex",name:"GCP Vertex AI",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://cloud.google.com/vertex-ai",envVarPrefix:"GOOGLE_VERTEX",requiredEnvVars:["GOOGLE_APPLICATION_CREDENTIALS"]},{id:"groq",name:"Groq",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://console.groq.com/docs",envVarPrefix:"GROQ",requiredEnvVars:["GROQ_API_KEY"]},{id:"fireworks",name:"Fireworks AI",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://docs.fireworks.ai",envVarPrefix:"FIREWORKS",requiredEnvVars:["FIREWORKS_API_KEY"]},{id:"together",name:"Together AI",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://docs.together.ai",envVarPrefix:"TOGETHER",requiredEnvVars:["TOGETHER_API_KEY"]},{id:"huggingface",name:"Hugging Face",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://huggingface.co/docs/inference-providers",envVarPrefix:"HF",requiredEnvVars:["HF_API_KEY"]},{id:"replicate",name:"Replicate",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://replicate.com/docs",envVarPrefix:"REPLICATE",requiredEnvVars:["REPLICATE_API_TOKEN"]},{id:"lepton",name:"Lepton AI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://www.lepton.ai/docs",baseURL:"https://api.lepton.ai/v1",envVarPrefix:"LEPTON",requiredEnvVars:["LEPTON_API_KEY"]},{id:"anyscale",name:"Anyscale Endpoints",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://docs.endpoints.anyscale.com/",baseURL:"https://api.endpoints.anyscale.com/v1",envVarPrefix:"ANYSCALE",requiredEnvVars:["ANYSCALE_API_KEY"]},{id:"octoai",name:"OctoAI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://octoai.cloud/docs",baseURL:"https://text.octoai.run/v1",envVarPrefix:"OCTOAI",requiredEnvVars:["OCTOAI_TOKEN"]},{id:"deepinfra",name:"DeepInfra",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://deepinfra.com/docs",baseURL:"https://api.deepinfra.com/v1/openai",envVarPrefix:"DEEPINFRA",requiredEnvVars:["DEEPINFRA_API_KEY"]},{id:"novita",name:"Novita AI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://novita.ai/docs",baseURL:"https://api.novita.ai/v3/openai",envVarPrefix:"NOVITA",requiredEnvVars:["NOVITA_API_KEY"]},{id:"black-forest-labs",name:"Black Forest Labs (FLUX)",category:"\u591A\u6A21\u6001",status:"ai-sdk",docs:"https://docs.bfl.ml",envVarPrefix:"BFL",requiredEnvVars:["BFL_API_KEY"]},{id:"elevenlabs",name:"ElevenLabs (TTS)",category:"\u591A\u6A21\u6001",status:"ai-sdk",docs:"https://elevenlabs.io/docs",envVarPrefix:"ELEVENLABS",requiredEnvVars:["ELEVENLABS_API_KEY"]},{id:"runway",name:"Runway (Video)",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://runwayml.com",envVarPrefix:"RUNWAY",requiredEnvVars:["RUNWAY_API_KEY"]},{id:"luma",name:"Luma (Video)",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://lumalabs.ai",envVarPrefix:"LUMA",requiredEnvVars:["LUMA_API_KEY"]},{id:"midjourney",name:"Midjourney",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://docs.midjourney.com",envVarPrefix:"MIDJOURNEY",requiredEnvVars:[]},{id:"ollama",name:"Ollama (\u672C\u5730)",category:"\u672C\u5730\u90E8\u7F72",status:"opencode",docs:"https://github.com/ollama/ollama",baseURL:"http://localhost:11434/v1",envVarPrefix:"OLLAMA",requiredEnvVars:["OLLAMA_BASE_URL"]},{id:"lmstudio",name:"LM Studio",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://lmstudio.ai/docs",baseURL:"http://localhost:1234/v1",envVarPrefix:"LMSTUDIO",requiredEnvVars:[]},{id:"vllm",name:"vLLM",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://docs.vllm.ai",baseURL:"http://localhost:8000/v1",envVarPrefix:"VLLM",requiredEnvVars:[]},{id:"tgi",name:"HF TGI",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://huggingface.co/docs/text-generation-inference",baseURL:"http://localhost:8080/v1",envVarPrefix:"TGI",requiredEnvVars:[]}],np=nn.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var zs=["openai","anthropic","google"],Js=["openai"];function on(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let n=t.length>0?t:[...zs];return{mode:"gateway",providerIds:n,customEndpoint:e.customEndpoint,routing:{profile:"multi-provider-gateway",providerSeed:n,runtimeGovernance:!0}}}case"direct":{let n=t.length>0?t:[...Js];return{mode:"direct",providerIds:n,customEndpoint:e.customEndpoint,routing:{profile:"direct-adapters",providerSeed:n,runtimeGovernance:!1}}}case"custom":return{mode:"custom",providerIds:t,customEndpoint:e.customEndpoint,routing:{profile:"openai-compatible",providerSeed:t,runtimeGovernance:!0}};case"none":return{mode:"none",providerIds:[],routing:{profile:"disabled",providerSeed:[],runtimeGovernance:!1}}}}var He=[{id:"wechat",name:"\u5FAE\u4FE1\u5F00\u653E\u5E73\u53F0",region:"cn",envVars:["WECHAT_APP_ID","WECHAT_APP_SECRET"],docs:"https://open.weixin.qq.com/cgi-bin/showdocument",callbackUrl:"/api/auth/callback/wechat",tokenEndpoint:"https://api.weixin.qq.com/sns/oauth2/access_token"},{id:"qq",name:"QQ \u767B\u5F55",region:"cn",envVars:["QQ_APP_ID","QQ_APP_KEY"],docs:"https://wiki.connect.qq.com",callbackUrl:"/api/auth/callback/qq",tokenEndpoint:"https://graph.qq.com/oauth2.0/token"},{id:"dingtalk",name:"\u9489\u9489",region:"cn",envVars:["DINGTALK_APP_ID","DINGTALK_APP_SECRET"],docs:"https://open.dingtalk.com/document/",callbackUrl:"/api/auth/callback/dingtalk",tokenEndpoint:"https://api.dingtalk.com/v1.0/oauth2/userAccessToken"},{id:"workweixin",name:"\u4F01\u4E1A\u5FAE\u4FE1",region:"cn",envVars:["WORKWEIXIN_CORP_ID","WORKWEIXIN_AGENT_ID","WORKWEIXIN_SECRET"],docs:"https://developer.work.weixin.qq.com",callbackUrl:"/api/auth/callback/workweixin",tokenEndpoint:"https://qyapi.weixin.qq.com/cgi-bin/gettoken"},{id:"feishu",name:"\u98DE\u4E66 / Lark",region:"cn",envVars:["FEISHU_APP_ID","FEISHU_APP_SECRET"],docs:"https://open.feishu.cn/document/",callbackUrl:"/api/auth/callback/feishu",tokenEndpoint:"https://open.feishu.cn/open-apis/authen/v1/access_token"},{id:"weibo",name:"\u5FAE\u535A",region:"cn",envVars:["WEIBO_APP_KEY","WEIBO_APP_SECRET"],docs:"https://open.weibo.com/wiki/",callbackUrl:"/api/auth/callback/weibo",tokenEndpoint:"https://api.weibo.com/oauth2/access_token"}],Qs=new Set(He.map(e=>e.id));function Un(e){return He.find(t=>t.id===e)}function Mn(e){if(!e)return[];let t=e.split(",").map(s=>s.trim().toLowerCase()).filter(Boolean);if(t.includes("none"))return[];let n=[],o=new Set;for(let s of t)Qs.has(s)&&!o.has(s)&&(n.push(s),o.add(s));return n}import ee from"fs";import T from"path";import{fileURLToPath as Zs}from"url";var er=Zs(import.meta.url),Dn=T.dirname(er),tr={web:"vercel","landing-page":"vercel","design-docs":"vercel","sailor-docs":"vercel",gateway:"cloudflare-workers","python-ai":"ecs-docker"};function nr(){let e=[T.join(Dn,"..","templates","deploy"),T.join(Dn,"..","..","templates","deploy")];for(let t of e)if(ee.existsSync(t))return t;return e[0]}function jn(e){switch(e){case"cloudflare":return{web:"cloudflare-pages","landing-page":"cloudflare-pages","design-docs":"cloudflare-pages","sailor-docs":"cloudflare-pages",gateway:"cloudflare-workers","python-ai":"ecs-docker"};case"selfhost":return{web:"standalone","landing-page":"standalone","design-docs":"standalone","sailor-docs":"standalone",gateway:"ecs-docker","python-ai":"ecs-docker"};case"railway":return{web:"railway","landing-page":"railway","design-docs":"railway","sailor-docs":"railway",gateway:"railway","python-ai":"railway"};case"none":case"vercel":return{...tr}}}function or(e){return`DEPLOY_TARGET_${e.toUpperCase().replace(/-/g,"_")}`}async function Fn(e,t){let n=T.join(e,"backends","gateway");ee.existsSync(n)&&await ee.promises.copyFile(T.join(t,"wrangler.gateway.toml"),T.join(n,"wrangler.toml"))}async function Bn(e,t){let n=T.join(e,".env.example"),o;try{o=await ee.promises.readFile(n,"utf8")}catch(i){if(i.code==="ENOENT")return;throw i}if(o.includes("# Deployment Targets"))return;let r=["","# Deployment Targets",...Object.entries(t).map(([i,a])=>`${or(i)}="${a}"`)].join(`
|
|
6
|
-
`);await ee.promises.appendFile(n,`${
|
|
7
|
-
`)}async function Vn(e,t){if(t==="none")return;let n=
|
|
8
|
-
`)),process.exit(130)}})}async function Yn(e,t){let n=!!e.region,o=!!e.auth,
|
|
5
|
+
`)),"fumadocs"}return"fumadocs"}function Zt(e){switch(e){case"vercel":return"vercel";case"railway":return"railway";case"cloudflare":return"cloudflare";case"selfhost":return"selfhost";case"none":return"none";default:return"vercel"}}function en(e){if(!e)return"global";let t=e.toLowerCase();return t==="cn"?"cn":t==="hybrid"?"hybrid":"global"}function Ln(e){return{...e==="cn"?{email:"aliyun-dm",storage:"aliyun-oss",monitoring:"sentry",analytics:"baidu",sms:"aliyun-sms"}:e==="hybrid"?{email:"resend",storage:"aliyun-oss",monitoring:"sentry",analytics:"posthog",sms:"aliyun-sms"}:{email:"resend",storage:"r2",monitoring:"sentry",analytics:"posthog",sms:"twilio"},queue:"none",search:"none",cache:e==="global"?"upstash-redis":e==="cn"?"redis":"upstash-redis",notifications:"none",webhooks:"none",cms:"none",featureFlags:"none",captcha:"none",mcp:"on",metering:"auto",billingMode:"usage",idp:"clerk",accessGate:"none"}}function tn(e){return e==="cn"?"wechat":"stripe"}import*as Y from"@clack/prompts";import is from"picocolors";var nn=[{id:"anthropic",name:"Anthropic",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://docs.anthropic.com",envVarPrefix:"ANTHROPIC",requiredEnvVars:["ANTHROPIC_API_KEY"]},{id:"openai",name:"OpenAI",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.openai.com/docs",envVarPrefix:"OPENAI",requiredEnvVars:["OPENAI_API_KEY"]},{id:"deepseek",name:"DeepSeek",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.deepseek.com/api-docs",envVarPrefix:"DEEPSEEK",requiredEnvVars:["DEEPSEEK_API_KEY"]},{id:"xai",name:"xAI (Grok)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://docs.x.ai/api",envVarPrefix:"XAI",requiredEnvVars:["XAI_API_KEY"]},{id:"moonshot",name:"Moonshot (Kimi)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"opencode",docs:"https://platform.moonshot.cn/docs",envVarPrefix:"MOONSHOT",requiredEnvVars:["MOONSHOT_API_KEY","MOONSHOT_BASE_URL"]},{id:"google",name:"Google Gemini",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://ai.google.dev/gemini-api/docs",envVarPrefix:"GOOGLE_GENERATIVE_AI",requiredEnvVars:["GOOGLE_GENERATIVE_AI_API_KEY"]},{id:"mistral",name:"Mistral AI",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://docs.mistral.ai",envVarPrefix:"MISTRAL",requiredEnvVars:["MISTRAL_API_KEY"]},{id:"cohere",name:"Cohere",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"ai-sdk",docs:"https://docs.cohere.com",envVarPrefix:"COHERE",requiredEnvVars:["COHERE_API_KEY"]},{id:"perplexity",name:"Perplexity",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://docs.perplexity.ai",baseURL:"https://api.perplexity.ai",envVarPrefix:"PERPLEXITY",requiredEnvVars:["PERPLEXITY_API_KEY"]},{id:"ai21",name:"AI21 Labs",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://docs.ai21.com",baseURL:"https://api.ai21.com/studio/v1",envVarPrefix:"AI21",requiredEnvVars:["AI21_API_KEY"]},{id:"upstage",name:"Upstage (Solar)",category:"\u76F4\u63A5\u5B9E\u9A8C\u5BA4",status:"cn-compatible",docs:"https://developers.upstage.ai/docs",baseURL:"https://api.upstage.ai/v1/solar",envVarPrefix:"UPSTAGE",requiredEnvVars:["UPSTAGE_API_KEY"]},{id:"siliconflow",name:"\u7845\u57FA\u6D41\u52A8 SiliconFlow",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://docs.siliconflow.cn",baseURL:"https://api.siliconflow.cn/v1",envVarPrefix:"SILICONFLOW",requiredEnvVars:["SILICONFLOW_API_KEY"]},{id:"volcengine-ark",name:"\u706B\u5C71\u5F15\u64CE ARK (\u8C46\u5305)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://www.volcengine.com/docs/82379",baseURL:"https://ark.cn-beijing.volces.com/api/v3",envVarPrefix:"ARK",requiredEnvVars:["ARK_API_KEY"]},{id:"bailian",name:"\u767E\u70BC Bailian (\u901A\u4E49)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://help.aliyun.com/zh/model-studio",baseURL:"https://dashscope.aliyuncs.com/compatible-mode/v1",envVarPrefix:"DASHSCOPE",requiredEnvVars:["DASHSCOPE_API_KEY"]},{id:"zhipu",name:"\u667A\u8C31 AI Zhipu",category:"\u56FD\u5185\u5E73\u53F0",status:"ai-sdk",docs:"https://docs.bigmodel.cn",baseURL:"https://open.bigmodel.cn/api/paas/v4",envVarPrefix:"ZHIPU",requiredEnvVars:["ZHIPU_API_KEY"]},{id:"baichuan",name:"\u767E\u5DDD\u667A\u80FD Baichuan",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.baichuan-ai.com/docs",baseURL:"https://api.baichuan-ai.com/v1",envVarPrefix:"BAICHUAN",requiredEnvVars:["BAICHUAN_API_KEY"]},{id:"minimax",name:"MiniMax (ABAB)",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.minimaxi.com/document/guides",baseURL:"https://api.minimax.chat/v1",envVarPrefix:"MINIMAX",requiredEnvVars:["MINIMAX_API_KEY","MINIMAX_GROUP_ID"]},{id:"stepfun",name:"\u9636\u8DC3\u661F\u8FB0 StepFun",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.stepfun.com/docs",baseURL:"https://api.stepfun.com/v1",envVarPrefix:"STEPFUN",requiredEnvVars:["STEPFUN_API_KEY"]},{id:"sensetime",name:"\u5546\u6C64 SenseNova",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.sensetime.com",baseURL:"https://api.sensenova.cn/v1",envVarPrefix:"SENSENOVA",requiredEnvVars:["SENSENOVA_API_KEY"]},{id:"tencent",name:"\u817E\u8BAF\u6DF7\u5143 Hunyuan",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://cloud.tencent.com/document/product/1729",baseURL:"https://api.hunyuan.cloud.tencent.com/v1",envVarPrefix:"HUNYUAN",requiredEnvVars:["HUNYUAN_API_KEY"]},{id:"lingyi",name:"\u96F6\u4E00\u4E07\u7269 Yi",category:"\u56FD\u5185\u5E73\u53F0",status:"cn-compatible",docs:"https://platform.lingyiwanwu.com/docs",baseURL:"https://api.lingyiwanwu.com/v1",envVarPrefix:"YI",requiredEnvVars:["YI_API_KEY"]},{id:"openrouter",name:"OpenRouter",category:"\u7EDF\u4E00\u7F51\u5173",status:"opencode",docs:"https://openrouter.ai/docs",envVarPrefix:"OPENROUTER",requiredEnvVars:["OPENROUTER_API_KEY"]},{id:"vercel-gateway",name:"Vercel AI Gateway",category:"\u7EDF\u4E00\u7F51\u5173",status:"opencode",docs:"https://vercel.com/docs/ai-gateway",envVarPrefix:"AI_GATEWAY",requiredEnvVars:["AI_GATEWAY_API_KEY"]},{id:"litellm",name:"LiteLLM Proxy",category:"\u7EDF\u4E00\u7F51\u5173",status:"cn-compatible",docs:"https://docs.litellm.ai",baseURL:"http://localhost:4000/v1",envVarPrefix:"LITELLM",requiredEnvVars:["LITELLM_API_KEY"]},{id:"portkey",name:"Portkey",category:"\u7EDF\u4E00\u7F51\u5173",status:"cn-compatible",docs:"https://portkey.ai/docs",baseURL:"https://api.portkey.ai/v1",envVarPrefix:"PORTKEY",requiredEnvVars:["PORTKEY_API_KEY"]},{id:"aws-bedrock",name:"AWS Bedrock",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://aws.amazon.com/bedrock/",envVarPrefix:"AWS_BEDROCK",requiredEnvVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_REGION"]},{id:"azure-openai",name:"Azure OpenAI",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://azure.microsoft.com/en-us/products/cognitive-services/openai-service/",envVarPrefix:"AZURE_OPENAI",requiredEnvVars:["AZURE_OPENAI_API_KEY","AZURE_OPENAI_ENDPOINT"]},{id:"gcp-vertex",name:"GCP Vertex AI",category:"\u4E91\u5E73\u53F0",status:"ai-sdk",docs:"https://cloud.google.com/vertex-ai",envVarPrefix:"GOOGLE_VERTEX",requiredEnvVars:["GOOGLE_APPLICATION_CREDENTIALS"]},{id:"groq",name:"Groq",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://console.groq.com/docs",envVarPrefix:"GROQ",requiredEnvVars:["GROQ_API_KEY"]},{id:"fireworks",name:"Fireworks AI",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://docs.fireworks.ai",envVarPrefix:"FIREWORKS",requiredEnvVars:["FIREWORKS_API_KEY"]},{id:"together",name:"Together AI",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://docs.together.ai",envVarPrefix:"TOGETHER",requiredEnvVars:["TOGETHER_API_KEY"]},{id:"huggingface",name:"Hugging Face",category:"\u63A8\u7406\u52A0\u901F",status:"opencode",docs:"https://huggingface.co/docs/inference-providers",envVarPrefix:"HF",requiredEnvVars:["HF_API_KEY"]},{id:"replicate",name:"Replicate",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://replicate.com/docs",envVarPrefix:"REPLICATE",requiredEnvVars:["REPLICATE_API_TOKEN"]},{id:"lepton",name:"Lepton AI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://www.lepton.ai/docs",baseURL:"https://api.lepton.ai/v1",envVarPrefix:"LEPTON",requiredEnvVars:["LEPTON_API_KEY"]},{id:"anyscale",name:"Anyscale Endpoints",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://docs.endpoints.anyscale.com/",baseURL:"https://api.endpoints.anyscale.com/v1",envVarPrefix:"ANYSCALE",requiredEnvVars:["ANYSCALE_API_KEY"]},{id:"octoai",name:"OctoAI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://octoai.cloud/docs",baseURL:"https://text.octoai.run/v1",envVarPrefix:"OCTOAI",requiredEnvVars:["OCTOAI_TOKEN"]},{id:"deepinfra",name:"DeepInfra",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://deepinfra.com/docs",baseURL:"https://api.deepinfra.com/v1/openai",envVarPrefix:"DEEPINFRA",requiredEnvVars:["DEEPINFRA_API_KEY"]},{id:"novita",name:"Novita AI",category:"\u63A8\u7406\u52A0\u901F",status:"cn-compatible",docs:"https://novita.ai/docs",baseURL:"https://api.novita.ai/v3/openai",envVarPrefix:"NOVITA",requiredEnvVars:["NOVITA_API_KEY"]},{id:"black-forest-labs",name:"Black Forest Labs (FLUX)",category:"\u591A\u6A21\u6001",status:"ai-sdk",docs:"https://docs.bfl.ml",envVarPrefix:"BFL",requiredEnvVars:["BFL_API_KEY"]},{id:"elevenlabs",name:"ElevenLabs (TTS)",category:"\u591A\u6A21\u6001",status:"ai-sdk",docs:"https://elevenlabs.io/docs",envVarPrefix:"ELEVENLABS",requiredEnvVars:["ELEVENLABS_API_KEY"]},{id:"runway",name:"Runway (Video)",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://runwayml.com",envVarPrefix:"RUNWAY",requiredEnvVars:["RUNWAY_API_KEY"]},{id:"luma",name:"Luma (Video)",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://lumalabs.ai",envVarPrefix:"LUMA",requiredEnvVars:["LUMA_API_KEY"]},{id:"midjourney",name:"Midjourney",category:"\u591A\u6A21\u6001",status:"pending",docs:"https://docs.midjourney.com",envVarPrefix:"MIDJOURNEY",requiredEnvVars:[]},{id:"ollama",name:"Ollama (\u672C\u5730)",category:"\u672C\u5730\u90E8\u7F72",status:"opencode",docs:"https://github.com/ollama/ollama",baseURL:"http://localhost:11434/v1",envVarPrefix:"OLLAMA",requiredEnvVars:["OLLAMA_BASE_URL"]},{id:"lmstudio",name:"LM Studio",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://lmstudio.ai/docs",baseURL:"http://localhost:1234/v1",envVarPrefix:"LMSTUDIO",requiredEnvVars:[]},{id:"vllm",name:"vLLM",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://docs.vllm.ai",baseURL:"http://localhost:8000/v1",envVarPrefix:"VLLM",requiredEnvVars:[]},{id:"tgi",name:"HF TGI",category:"\u672C\u5730\u90E8\u7F72",status:"cn-compatible",docs:"https://huggingface.co/docs/text-generation-inference",baseURL:"http://localhost:8080/v1",envVarPrefix:"TGI",requiredEnvVars:[]}],rp=nn.reduce((e,t)=>(e[t.category]||(e[t.category]=[]),e[t.category].push(t),e),{});var zr=["openai","anthropic","google"],Jr=["openai"];function on(e){let t=e.providerIds??[];switch(e.mode){case"gateway":{let n=t.length>0?t:[...zr];return{mode:"gateway",providerIds:n,customEndpoint:e.customEndpoint,routing:{profile:"multi-provider-gateway",providerSeed:n,runtimeGovernance:!0}}}case"direct":{let n=t.length>0?t:[...Jr];return{mode:"direct",providerIds:n,customEndpoint:e.customEndpoint,routing:{profile:"direct-adapters",providerSeed:n,runtimeGovernance:!1}}}case"custom":return{mode:"custom",providerIds:t,customEndpoint:e.customEndpoint,routing:{profile:"openai-compatible",providerSeed:t,runtimeGovernance:!0}};case"none":return{mode:"none",providerIds:[],routing:{profile:"disabled",providerSeed:[],runtimeGovernance:!1}}}}var We=[{id:"wechat",name:"\u5FAE\u4FE1\u5F00\u653E\u5E73\u53F0",region:"cn",envVars:["WECHAT_APP_ID","WECHAT_APP_SECRET"],docs:"https://open.weixin.qq.com/cgi-bin/showdocument",callbackUrl:"/api/auth/callback/wechat",tokenEndpoint:"https://api.weixin.qq.com/sns/oauth2/access_token"},{id:"qq",name:"QQ \u767B\u5F55",region:"cn",envVars:["QQ_APP_ID","QQ_APP_KEY"],docs:"https://wiki.connect.qq.com",callbackUrl:"/api/auth/callback/qq",tokenEndpoint:"https://graph.qq.com/oauth2.0/token"},{id:"dingtalk",name:"\u9489\u9489",region:"cn",envVars:["DINGTALK_APP_ID","DINGTALK_APP_SECRET"],docs:"https://open.dingtalk.com/document/",callbackUrl:"/api/auth/callback/dingtalk",tokenEndpoint:"https://api.dingtalk.com/v1.0/oauth2/userAccessToken"},{id:"workweixin",name:"\u4F01\u4E1A\u5FAE\u4FE1",region:"cn",envVars:["WORKWEIXIN_CORP_ID","WORKWEIXIN_AGENT_ID","WORKWEIXIN_SECRET"],docs:"https://developer.work.weixin.qq.com",callbackUrl:"/api/auth/callback/workweixin",tokenEndpoint:"https://qyapi.weixin.qq.com/cgi-bin/gettoken"},{id:"feishu",name:"\u98DE\u4E66 / Lark",region:"cn",envVars:["FEISHU_APP_ID","FEISHU_APP_SECRET"],docs:"https://open.feishu.cn/document/",callbackUrl:"/api/auth/callback/feishu",tokenEndpoint:"https://open.feishu.cn/open-apis/authen/v1/access_token"},{id:"weibo",name:"\u5FAE\u535A",region:"cn",envVars:["WEIBO_APP_KEY","WEIBO_APP_SECRET"],docs:"https://open.weibo.com/wiki/",callbackUrl:"/api/auth/callback/weibo",tokenEndpoint:"https://api.weibo.com/oauth2/access_token"}],Qr=new Set(We.map(e=>e.id));function Un(e){return We.find(t=>t.id===e)}function Mn(e){if(!e)return[];let t=e.split(",").map(r=>r.trim().toLowerCase()).filter(Boolean);if(t.includes("none"))return[];let n=[],o=new Set;for(let r of t)Qr.has(r)&&!o.has(r)&&(n.push(r),o.add(r));return n}import ee from"fs";import T from"path";import{fileURLToPath as Zr}from"url";var es=Zr(import.meta.url),Dn=T.dirname(es),ts={web:"vercel","landing-page":"vercel","design-docs":"vercel","sailor-docs":"vercel",gateway:"cloudflare-workers","python-ai":"ecs-docker"};function ns(){let e=[T.join(Dn,"..","templates","deploy"),T.join(Dn,"..","..","templates","deploy")];for(let t of e)if(ee.existsSync(t))return t;return e[0]}function jn(e){switch(e){case"cloudflare":return{web:"cloudflare-pages","landing-page":"cloudflare-pages","design-docs":"cloudflare-pages","sailor-docs":"cloudflare-pages",gateway:"cloudflare-workers","python-ai":"ecs-docker"};case"selfhost":return{web:"standalone","landing-page":"standalone","design-docs":"standalone","sailor-docs":"standalone",gateway:"ecs-docker","python-ai":"ecs-docker"};case"railway":return{web:"railway","landing-page":"railway","design-docs":"railway","sailor-docs":"railway",gateway:"railway","python-ai":"railway"};case"none":case"vercel":return{...ts}}}function os(e){return`DEPLOY_TARGET_${e.toUpperCase().replace(/-/g,"_")}`}async function Fn(e,t){let n=T.join(e,"backends","gateway");ee.existsSync(n)&&await ee.promises.copyFile(T.join(t,"wrangler.gateway.toml"),T.join(n,"wrangler.toml"))}async function Bn(e,t){let n=T.join(e,".env.example"),o;try{o=await ee.promises.readFile(n,"utf8")}catch(i){if(i.code==="ENOENT")return;throw i}if(o.includes("# Deployment Targets"))return;let s=["","# Deployment Targets",...Object.entries(t).map(([i,a])=>`${os(i)}="${a}"`)].join(`
|
|
6
|
+
`);await ee.promises.appendFile(n,`${s}
|
|
7
|
+
`)}async function Vn(e,t){if(t==="none")return;let n=ns();t==="vercel"?(await ee.promises.copyFile(T.join(n,"vercel.json"),T.join(e,"vercel.json")),await Fn(e,n)):t==="railway"?await ee.promises.copyFile(T.join(n,"railway.toml"),T.join(e,"railway.toml")):t==="cloudflare"?(await ee.promises.copyFile(T.join(n,"wrangler.toml"),T.join(e,"wrangler.toml")),await Fn(e,n)):t==="selfhost"&&(await ee.promises.copyFile(T.join(n,"docker-compose.yml"),T.join(e,"docker-compose.yml")),await ee.promises.copyFile(T.join(n,"Dockerfile.web"),T.join(e,"Dockerfile.web")))}var rs={qstash:"foundation",bullmq:"foundation",upstash:"foundation",sqs:"foundation",meilisearch:"foundation",typesense:"foundation",algolia:"foundation",pgvector:"foundation","vercel-flags":"foundation",growthbook:"foundation",configcat:"foundation",turnstile:"wip",hcaptcha:"wip","aliyun-slide":"wip",invite:"foundation"};function ss(e){return e?rs[e]??"stable":"stable"}function Xe(e){switch(e){case"stable":return"";case"foundation":return"[Foundation]";case"wip":return"[WIP]";case"deprecated":return"[Deprecated]"}}function he(e){switch(e){case"stable":return"Production-ready.";case"foundation":return"Foundation status \u2014 core contracts work, but production use still requires provider credentials, adapter wiring, or a verified integration contract.";case"wip":return"WIP \u2014 actively being built, should not be used in production.";case"deprecated":return"Deprecated \u2014 scheduled for removal, do not use."}}function Kn(e){let t=[];for(let{flag:n,provider:o}of e){if(!o||o==="none")continue;let r=ss(o);r!=="stable"&&t.push({flag:n,provider:o,status:r})}return t}function Ee(e,t){if(e===void 0)return t;let n=String(e).trim().toLowerCase();return n==="true"||n==="1"||n==="yes"||n==="on"?!0:n==="false"||n==="0"||n==="no"||n==="off"?!1:t}function $n(e,t){let n=t==="cn";return{cronJobs:Ee(e.cronJobs,!0),auditLog:Ee(e.auditLog,!1),apiKeys:Ee(e.apiKeys,!0),webhooks:Ee(e.webhooks,!0),commandPalette:Ee(e.commandPalette,!0),cookieConsent:Ee(e.cookieConsent,!0),legalPages:Ee(e.legalPages,!0),chinaCompliance:Ee(e.chinaCompliance,n)}}async function as(e,t,n,o){let r={};return t||(r.region=()=>Y.select({message:"Target region?",options:[{value:"global",label:"global \u2014 \u6D77\u5916\u4F18\u5148"},{value:"cn",label:"cn \u2014 \u56FD\u5185\u4F18\u5148"},{value:"hybrid",label:"hybrid \u2014 \u53CC\u8F68\uFF08\u56FD\u5185+\u51FA\u6D77\uFF09"}],initialValue:"global"})),n||(r.auth=()=>Y.select({message:"Auth provider?",options:[{value:"clerk",label:"Clerk",hint:"managed, fastest setup"},{value:"betterauth",label:"Better Auth",hint:"self-hosted, modern (2FA / passkeys / RBAC)"},{value:"nextauth",label:"NextAuth (Auth.js v5)",hint:"self-hosted, mature, large ecosystem"},{value:"supabase",label:"Supabase Auth",hint:"managed auth with Supabase storage/realtime ecosystem"},{value:"none",label:"None"}],initialValue:"clerk"})),o||(r.aiMode=()=>Y.select({message:"AI topology?",options:[{value:"gateway",label:"Multi-provider AI Gateway / router",hint:"recommended"},{value:"direct",label:"Direct SDK/provider adapters"},{value:"custom",label:"OpenAI-compatible endpoint"},{value:"none",label:"Skip AI"}],initialValue:"gateway"}),r.aiProviders=({results:s})=>{if(s.aiMode!=="direct")return Promise.resolve([]);let i=nn.map(a=>({value:a.id,label:`[${a.category}] ${a.name}`}));return Y.multiselect({message:"Select direct AI provider adapters (expert path)",options:i,initialValues:["openai"],required:!1})},r.customAiName=({results:s})=>s.aiMode==="custom"?Y.text({message:"Custom endpoint name (e.g. proxy, local):",defaultValue:"custom",placeholder:"custom"}):Promise.resolve(void 0),r.customAiBaseUrl=({results:s})=>s.aiMode==="custom"?Y.text({message:"Custom endpoint base URL (e.g. https://api.proxy.com/v1):",validate:i=>{if(!i?.length)return"Base URL is required."}}):Promise.resolve(void 0),r.customAiApiKeyEnv=({results:s})=>s.aiMode==="custom"?Y.text({message:"Environment variable name for the API Key:",defaultValue:"CUSTOM_AI_API_KEY",placeholder:"CUSTOM_AI_API_KEY"}):Promise.resolve(void 0)),Object.keys(r).length===0?{}:await Y.group(r,{onCancel:()=>{process.stdout.write(is.red(`\u2718 Cancelled
|
|
8
|
+
`)),process.exit(130)}})}async function Yn(e,t){let n=!!e.region,o=!!e.auth,r=!!e.payment,s=!!e.ai,i=!!e.email,a=!!e.storage,c=!!e.monitoring,p=!!e.analytics,u=!!e.sms,d=e.i18n!==void 0,h=!!e.yes||!process.stdin.isTTY,f,E,S,m,P,G,M,ge=Mn(e.socialLogin),pe,Z,j,K,C,H,le;if(h){f=en(e.region),E=Gt(e.orm);{let $=Yt(e.db),yt=qt(e.dbHost,f,$);S=yt.engine,m=yt.hostId}let W=r?e.payment:tn(f);P=Ht(W),G=Wt(W),M=Xt(e.auth);let He="gateway";if(s){let $=e.ai?.trim().toLowerCase()??"";zt($)?He=$:He="direct"}let rt=on({mode:He,providerIds:s?Jt(e.ai):void 0});pe=rt.mode,Z=rt.routing,j=rt.providerIds,C=Zt(e.deploy),H=Qt(e.docs,t),le=d?!!e.i18n:!0}else{let W=await as(e,n,o,s);f=en(n?e.region:W.region),E=Gt(e.orm);{let yt=Yt(e.db),An=qt(e.dbHost,f,yt);S=An.engine,m=An.hostId}let He=r?e.payment:tn(f);P=Ht(He),G=Wt(He),M=Xt(o?e.auth:W.auth);let rt=W.aiMode==="custom"?{name:W.customAiName??"custom",baseURL:W.customAiBaseUrl??"",apiKeyEnvName:W.customAiApiKeyEnv??"CUSTOM_AI_API_KEY"}:void 0,$=on({mode:s?e.ai?.trim().toLowerCase()==="none"?"none":"direct":W.aiMode??"gateway",providerIds:s?Jt(e.ai):W.aiProviders,customEndpoint:rt});pe=$.mode,Z=$.routing,j=$.providerIds,$.customEndpoint&&(K={name:$.customEndpoint.name,baseURL:$.customEndpoint.baseURL,apiKeyEnvName:$.customEndpoint.apiKeyEnvName}),C=Zt(e.deploy),H=Qt(e.docs,t),le=d?!!e.i18n:!0}let w=Ln(f),fe=i?e.email:w.email,qe=On(a?e.storage:void 0,w.storage),Ge=c?e.monitoring:w.monitoring,ye=p?e.analytics:w.analytics,v=u?e.sms:w.sms,k=e.queue??w.queue,I=e.search??w.search,x=e.cache??w.cache,Mt=e.notifications??w.notifications,Dt=e.webhooks??w.webhooks,En=e.cms??w.cms,Ft=e.featureFlags??w.featureFlags,jt=e.captcha??w.captcha,vn=e.mcp??w.mcp,bn=e.metering??w.metering,_n=e.billingMode??w.billingMode,Pn=e.idp??w.idp,Bt=e.accessGate==="invite"?"invite":w.accessGate,wn=jn(C),Se=$n({cronJobs:e.cronJobs,auditLog:e.auditLog,apiKeys:e.apiKeys,commandPalette:e.commandPalette,cookieConsent:e.cookieConsent,legalPages:e.legalPages,chinaCompliance:e.chinaCompliance},f),$r=Kn([{flag:"queue",provider:k},{flag:"search",provider:I},{flag:"notifications",provider:Mt},{flag:"webhooks",provider:Dt},{flag:"feature-flags",provider:Ft},{flag:"captcha",provider:jt},{flag:"access-gate",provider:Bt}]),Yr={region:f,orm:E,database:S,databaseHost:m,payment:P,aiMode:pe,aiRouting:Z,aiProviders:j,customAiEndpoint:K,deployTarget:C,deployTargets:wn,docs:H,i18n:le,email:fe,storage:qe,monitoring:Ge,analytics:ye,sms:v,queue:k,search:I,cache:x,notifications:Mt,webhooks:Dt,cms:En,featureFlags:Ft,captcha:jt,mcp:vn,metering:bn,billingMode:_n,idp:Pn,accessGate:Bt,cronJobs:Se.cronJobs,auditLog:Se.auditLog,apiKeys:Se.apiKeys,commandPalette:Se.commandPalette,cookieConsent:Se.cookieConsent,legalPages:Se.legalPages,chinaCompliance:Se.chinaCompliance};return{region:f,orm:E,database:S,databaseHost:m,payment:P,paymentChoice:G,auth:M,socialLoginIds:ge,aiMode:pe,aiRouting:Z,aiProviders:j,customAiEndpoint:K,deployTarget:C,deployTargets:wn,docs:H,i18n:le,email:fe,storage:qe,monitoring:Ge,analytics:ye,sms:v,queue:k,search:I,cache:x,notifications:Mt,webhooks:Dt,cms:En,featureFlags:Ft,captcha:jt,mcp:vn,metering:bn,billingMode:_n,idp:Pn,accessGate:Bt,waveToggles:Se,previewSelections:$r,config:Yr}}import{execFileSync as Ot}from"child_process";import Lt from"fs";import $e from"path";import gt from"picocolors";import kc from"update-notifier";import A from"picocolors";function cs(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function qn(e){let t=cs(),n=t?"\u2693":"-",o=t?"\u25B8":"->",r=t?"\u2605":"*",s=t?"\u{1F4E7}":"*",a=["",` ${t?A.bold(`${n} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`):`${n} Done in ${e.elapsedSec}s \xB7 ${e.targetDir}/`}`,"",` ${t?A.bold("Next:"):"Next:"}`,` ${o} cd ${e.targetDir}`];e.skippedInstall&&a.push(` ${o} pnpm install (if --no-install was set)`),a.push(` ${o} fill in .env.local ${t?A.dim("\u2192 add provider keys before booting apps"):"-> add provider keys before booting apps"}`,` ${o} pnpm db:migrate ${t?A.dim("\u2192 sync Prisma schema"):"-> sync Prisma schema"}`,` ${o} pnpm db:seed ${t?A.dim("\u2192 load example tenants and records"):"-> load example tenants and records"}`,` ${o} pnpm dev ${t?A.dim("\u2192 http://localhost:3000"):"-> http://localhost:3000"}`,"",` ${t?A.bold("Customize:"):"Customize:"}`,` ${o} pnpm brand:init ${t?A.dim("\u2192 create brand.config.ts"):"-> create brand.config.ts"}`,` ${o} pnpm brand:apply ${t?A.dim("\u2192 propagate brand changes"):"-> propagate brand changes"}`,` ${o} pnpm preset:env ${t?A.dim("\u2192 review preset env requirements"):"-> review preset env requirements"}`,"",` ${t?A.bold("Useful scripts:"):"Useful scripts:"}`,` ${o} pnpm infra:up ${t?A.dim("\u2192 start local PostgreSQL/Redis/ClickHouse"):"-> start local PostgreSQL/Redis/ClickHouse"}`,` ${o} pnpm generate:api-types ${t?A.dim("\u2192 refresh shared API client types"):"-> refresh shared API client types"}`,` ${o} pnpm lint ${t?A.dim("\u2192 quick repo sanity check"):"-> quick repo sanity check"}`,` ${o} pnpm audit ${t?A.dim("\u2192 scan deps for known CVEs"):"-> scan deps for known CVEs"}`);let c=e.previewSelections??[];if(c.length>0){let _=t?A.bold(A.yellow("\u26A0 Preview features selected:")):"!! Preview features selected:";a.push("",` ${_}`);for(let h of c){let f=Xe(h.status),E=` ${o} ${h.flag} (${h.provider}) ${f}`;a.push(t?A.yellow(E):E)}a.push("",` ${t?A.dim(he("foundation")):he("foundation")}`,` ${t?A.dim("You may need to contribute the provider integration yourself."):"You may need to contribute the provider integration yourself."}`,` ${t?A.dim("See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"):"See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md"}`)}let p=e.waveFeatures??{},u=_=>_!==!1,d=[];u(p.apiKeys)&&d.push("Manage API keys at /settings/api-keys"),u(p.auditLog)&&d.push("View audit log at /settings/audit-log"),d.push("Configure webhooks at /settings/webhooks"),u(p.commandPalette)&&d.push("Press Cmd/Ctrl+K to open the command palette"),d.push("Edit notification preferences at /settings/notifications"),d.push("Export your data at /settings/account/export"),p.chinaCompliance&&d.push("China deployments \u2014 see packages/ops/china-compliance/README.md"),a.push("",` ${t?A.bold("What you can do next:"):"What you can do next:"}`);for(let _ of d)a.push(` ${o} ${_}`);a.push("",` ${t?A.bold("Ship faster:"):"Ship faster:"}`,` ${r} Star us https://github.com/nebutra/nebutra-sailor`,` ${s} Free license https://nebutra.com/get-license`,""),process.stdout.write(a.join(`
|
|
9
9
|
`)+`
|
|
10
|
-
`)}import
|
|
11
|
-
`+t):
|
|
10
|
+
`)}import ze from"fs";import B from"path";var Gn=[{id:"posthog",name:"PostHog",region:"both",envVars:["POSTHOG_KEY","POSTHOG_HOST","NEXT_PUBLIC_POSTHOG_KEY","NEXT_PUBLIC_POSTHOG_HOST"],docs:"https://posthog.com/docs",pkgs:["posthog-js","posthog-node"],providerFile:"apps/web/src/lib/analytics/posthog.client.ts"},{id:"plausible",name:"Plausible",region:"global",envVars:["NEXT_PUBLIC_PLAUSIBLE_DOMAIN","NEXT_PUBLIC_PLAUSIBLE_SRC"],docs:"https://plausible.io/docs",providerFile:"apps/web/src/components/analytics/PlausibleScript.tsx"},{id:"umami",name:"Umami",region:"both",envVars:["NEXT_PUBLIC_UMAMI_WEBSITE_ID","NEXT_PUBLIC_UMAMI_SRC"],docs:"https://umami.is/docs",providerFile:"apps/web/src/components/analytics/UmamiScript.tsx"},{id:"mixpanel",name:"Mixpanel",region:"global",envVars:["MIXPANEL_TOKEN","NEXT_PUBLIC_MIXPANEL_TOKEN"],docs:"https://docs.mixpanel.com",pkgs:["mixpanel-browser","mixpanel"],providerFile:"apps/web/src/lib/analytics/mixpanel.client.ts"},{id:"baidu",name:"\u767E\u5EA6\u7EDF\u8BA1 Baidu Tongji",region:"cn",envVars:["NEXT_PUBLIC_BAIDU_STATS_ID"],docs:"https://tongji.baidu.com",providerFile:"apps/web/src/components/analytics/BaiduStatsScript.tsx"},{id:"sensors",name:"\u795E\u7B56 Sensors Analytics",region:"cn",envVars:["NEXT_PUBLIC_SENSORS_SERVER_URL","NEXT_PUBLIC_SENSORS_APP_JS_URL"],docs:"https://manual.sensorsdata.cn",pkgs:["sa-sdk-javascript"],providerFile:"apps/web/src/lib/analytics/sensors.client.ts"},{id:"growingio",name:"GrowingIO",region:"cn",envVars:["NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID"],docs:"https://growingio.com/docs",providerFile:"apps/web/src/components/analytics/GrowingIoScript.tsx"},{id:"none",name:"None",region:"both",envVars:[],docs:""}],Cp=Gn.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Hn(e){return Gn.find(t=>t.id===e)}function ps(e){ze.mkdirSync(e,{recursive:!0})}function te(e,t){ps(B.dirname(e)),ze.writeFileSync(e,t)}function Ie(e,t){let n=B.join(e,".env.example");ze.existsSync(n)?ze.appendFileSync(n,`
|
|
11
|
+
`+t):ze.writeFileSync(n,t)}function ls(e){let t=`"use client";
|
|
12
12
|
/**
|
|
13
13
|
* PostHog browser SDK \u2014 lazy-initialized on first access.
|
|
14
14
|
*/
|
|
@@ -91,12 +91,12 @@ export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
|
|
|
91
91
|
|
|
92
92
|
return <>{children}</>;
|
|
93
93
|
}
|
|
94
|
-
`;te(B.join(e,"src","lib","analytics","posthog.client.ts"),t),te(B.join(e,"src","lib","analytics","posthog.server.ts"),n),te(B.join(e,"src","components","analytics","AnalyticsProvider.tsx"),o)}function
|
|
94
|
+
`;te(B.join(e,"src","lib","analytics","posthog.client.ts"),t),te(B.join(e,"src","lib","analytics","posthog.server.ts"),n),te(B.join(e,"src","components","analytics","AnalyticsProvider.tsx"),o)}function ds(){return`# PostHog \u2014 product analytics
|
|
95
95
|
POSTHOG_KEY=
|
|
96
96
|
POSTHOG_HOST=https://us.i.posthog.com
|
|
97
97
|
NEXT_PUBLIC_POSTHOG_KEY=
|
|
98
98
|
NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
|
|
99
|
-
`}function
|
|
99
|
+
`}function us(e){te(B.join(e,"src","components","analytics","PlausibleScript.tsx"),`"use client";
|
|
100
100
|
/**
|
|
101
101
|
* Plausible script tag \u2014 lightweight, privacy-friendly analytics.
|
|
102
102
|
*/
|
|
@@ -116,10 +116,10 @@ export function PlausibleScript() {
|
|
|
116
116
|
/>
|
|
117
117
|
);
|
|
118
118
|
}
|
|
119
|
-
`)}function
|
|
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
|
|
122
|
+
`}function gs(e){te(B.join(e,"src","components","analytics","UmamiScript.tsx"),`"use client";
|
|
123
123
|
/**
|
|
124
124
|
* Umami analytics \u2014 self-hosted OR umami.is cloud.
|
|
125
125
|
*/
|
|
@@ -139,10 +139,10 @@ export function UmamiScript() {
|
|
|
139
139
|
/>
|
|
140
140
|
);
|
|
141
141
|
}
|
|
142
|
-
`)}function
|
|
142
|
+
`)}function fs(){return`# Umami \u2014 self-hostable analytics
|
|
143
143
|
NEXT_PUBLIC_UMAMI_WEBSITE_ID=
|
|
144
144
|
NEXT_PUBLIC_UMAMI_SRC=https://cloud.umami.is/script.js
|
|
145
|
-
`}function
|
|
145
|
+
`}function ys(e){let t=`"use client";
|
|
146
146
|
import mixpanel from "mixpanel-browser";
|
|
147
147
|
|
|
148
148
|
let initialized = false;
|
|
@@ -181,10 +181,10 @@ export function trackServer(
|
|
|
181
181
|
if (!c) return;
|
|
182
182
|
c.track(event, { distinct_id: distinctId, ...properties });
|
|
183
183
|
}
|
|
184
|
-
`;te(B.join(e,"src","lib","analytics","mixpanel.client.ts"),t),te(B.join(e,"src","lib","analytics","mixpanel.server.ts"),n)}function
|
|
184
|
+
`;te(B.join(e,"src","lib","analytics","mixpanel.client.ts"),t),te(B.join(e,"src","lib","analytics","mixpanel.server.ts"),n)}function Ss(){return`# Mixpanel \u2014 product analytics
|
|
185
185
|
MIXPANEL_TOKEN=
|
|
186
186
|
NEXT_PUBLIC_MIXPANEL_TOKEN=
|
|
187
|
-
`}function
|
|
187
|
+
`}function hs(e){te(B.join(e,"src","components","analytics","BaiduStatsScript.tsx"),`"use client";
|
|
188
188
|
/**
|
|
189
189
|
* \u767E\u5EA6\u7EDF\u8BA1 Baidu Tongji \u2014 hm.js \u57CB\u70B9\u811A\u672C.
|
|
190
190
|
*/
|
|
@@ -210,9 +210,9 @@ var _hmt = _hmt || [];
|
|
|
210
210
|
/>
|
|
211
211
|
);
|
|
212
212
|
}
|
|
213
|
-
`)}function
|
|
213
|
+
`)}function Es(){return`# \u767E\u5EA6\u7EDF\u8BA1 \u2014 \u4E2D\u56FD\u533A\u7F51\u7AD9\u5206\u6790
|
|
214
214
|
NEXT_PUBLIC_BAIDU_STATS_ID=
|
|
215
|
-
`}function
|
|
215
|
+
`}function vs(e){te(B.join(e,"src","lib","analytics","sensors.client.ts"),`"use client";
|
|
216
216
|
/**
|
|
217
217
|
* \u795E\u7B56\u5206\u6790 (Sensors Analytics) \u2014 sa-sdk-javascript \u5C01\u88C5.
|
|
218
218
|
*/
|
|
@@ -240,10 +240,10 @@ export function initSensors(): void {
|
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
export { sensors };
|
|
243
|
-
`)}function
|
|
243
|
+
`)}function bs(){return`# \u795E\u7B56\u5206\u6790 Sensors Analytics
|
|
244
244
|
NEXT_PUBLIC_SENSORS_SERVER_URL=
|
|
245
245
|
NEXT_PUBLIC_SENSORS_APP_JS_URL=
|
|
246
|
-
`}function
|
|
246
|
+
`}function _s(e){te(B.join(e,"src","components","analytics","GrowingIoScript.tsx"),`"use client";
|
|
247
247
|
/**
|
|
248
248
|
* GrowingIO CDP \u2014 inline snippet installer.
|
|
249
249
|
*/
|
|
@@ -268,21 +268,21 @@ gdp("send");
|
|
|
268
268
|
/>
|
|
269
269
|
);
|
|
270
270
|
}
|
|
271
|
-
`)}function
|
|
271
|
+
`)}function Ps(){return`# GrowingIO \u2014 \u5168\u57CB\u70B9 CDP (\u4E2D\u56FD\u533A)
|
|
272
272
|
NEXT_PUBLIC_GROWINGIO_ACCOUNT_ID=
|
|
273
|
-
`}async function Wn(e,t,n="global"){let o=Hn(t);if(!o||o.id==="none")return;let
|
|
274
|
-
`+t):q.writeFileSync(n,t)}function
|
|
275
|
-
`+t)}async function zn(e,t){let n=N.join(e,"packages","iam","auth");if(!q.existsSync(n))return;if(t==="none"){V(n),
|
|
273
|
+
`}async function Wn(e,t,n="global"){let o=Hn(t);if(!o||o.id==="none")return;let r=B.join(e,"apps","web");if(!ze.existsSync(r))return;let s=o.id;try{switch(s){case"posthog":ls(r),Ie(e,ds());return;case"plausible":us(r),Ie(e,ms());return;case"umami":gs(r),Ie(e,fs());return;case"mixpanel":ys(r),Ie(e,Ss());return;case"baidu":hs(r),Ie(e,Es());return;case"sensors":vs(r),Ie(e,bs());return;case"growingio":_s(r),Ie(e,Ps());return;default:return}}catch(i){throw console.error(`Failed to apply analytics selection "${t}":`,i),new Error(`Analytics scaffold for "${t}" failed \u2014 see stderr for details.`)}}var ws="https://analytics.nebutra.com";function As(e={}){if(e.noTelemetry===!0)return!0;let t=process.env.NEBUTRA_TELEMETRY;return t==="0"||t==="false"}function Xn(e,t={}){As(t)||(async()=>{try{let n=await import("./dist-B346V4U6.js");if(typeof n.createProductAnalyticsClient!="function")return;let o=n.createProductAnalyticsClient({posthog:{apiKey:process.env.POSTHOG_KEY??process.env.NEXT_PUBLIC_POSTHOG_KEY??process.env.NEBUTRA_POSTHOG_KEY??"",host:process.env.POSTHOG_HOST??process.env.NEXT_PUBLIC_POSTHOG_HOST??process.env.NEBUTRA_POSTHOG_HOST??ws},onError:()=>{}});if(typeof o?.track!="function")return;let r=o.track("scaffold.completed",e);r&&typeof r.then=="function"&&await r.catch(()=>{})}catch{}})()}import q from"fs";import N from"path";function V(e){q.existsSync(e)&&q.rmSync(e,{recursive:!0,force:!0})}function St(e,t){let n=N.join(e,".env.example");q.existsSync(n)?q.appendFileSync(n,`
|
|
274
|
+
`+t):q.writeFileSync(n,t)}function ht(e,t){if(!q.existsSync(e))return;let n=q.readFileSync(e,"utf8"),o=n.replace(/export type AuthProviderId\s*=\s*(?:"[^"]+"\s*\|\s*)+"[^"]+";/,`export type AuthProviderId = "${t}";`);o!==n&&q.writeFileSync(e,o)}function Is(e,t){let n=N.join(e,"README.md");if(!q.existsSync(n)){q.writeFileSync(n,t);return}q.appendFileSync(n,`
|
|
275
|
+
`+t)}async function zn(e,t){let n=N.join(e,"packages","iam","auth");if(!q.existsSync(n))return;if(t==="none"){V(n),Is(e,`
|
|
276
276
|
## Auth
|
|
277
277
|
|
|
278
278
|
Auth was skipped at scaffold time (\`--auth=none\`). Add your preferred auth provider manually (e.g. Clerk, Better Auth, NextAuth, Supabase).
|
|
279
|
-
`);return}let o=N.join(n,"src","providers"),
|
|
279
|
+
`);return}let o=N.join(n,"src","providers"),r=N.join(n,"src","types.ts");if(t==="clerk"){V(N.join(o,"better-auth.ts")),V(N.join(o,"nextauth.ts")),V(N.join(o,"supabase.ts")),ht(r,"clerk"),St(e,`# Clerk auth
|
|
280
280
|
CLERK_PUBLISHABLE_KEY=
|
|
281
281
|
CLERK_SECRET_KEY=
|
|
282
|
-
`);return}if(t==="betterauth"){V(N.join(o,"clerk.ts")),V(N.join(o,"nextauth.ts")),V(N.join(o,"supabase.ts")),
|
|
282
|
+
`);return}if(t==="betterauth"){V(N.join(o,"clerk.ts")),V(N.join(o,"nextauth.ts")),V(N.join(o,"supabase.ts")),ht(r,"better-auth"),St(e,`# Better Auth
|
|
283
283
|
BETTER_AUTH_SECRET=
|
|
284
284
|
BETTER_AUTH_URL=http://localhost:3000
|
|
285
|
-
`);return}if(t==="nextauth"){V(N.join(o,"clerk.ts")),V(N.join(o,"better-auth.ts")),V(N.join(o,"supabase.ts")),
|
|
285
|
+
`);return}if(t==="nextauth"){V(N.join(o,"clerk.ts")),V(N.join(o,"better-auth.ts")),V(N.join(o,"supabase.ts")),ht(r,"nextauth"),St(e,`# NextAuth (Auth.js v5)
|
|
286
286
|
AUTH_SECRET=
|
|
287
287
|
NEXTAUTH_URL=http://localhost:3000
|
|
288
288
|
# OAuth (optional \u2014 leave blank to disable that provider)
|
|
@@ -290,7 +290,7 @@ GOOGLE_CLIENT_ID=
|
|
|
290
290
|
GOOGLE_CLIENT_SECRET=
|
|
291
291
|
GITHUB_CLIENT_ID=
|
|
292
292
|
GITHUB_CLIENT_SECRET=
|
|
293
|
-
`);return}if(t==="supabase"){V(N.join(o,"clerk.ts")),V(N.join(o,"better-auth.ts")),V(N.join(o,"nextauth.ts")),
|
|
293
|
+
`);return}if(t==="supabase"){V(N.join(o,"clerk.ts")),V(N.join(o,"better-auth.ts")),V(N.join(o,"nextauth.ts")),ht(r,"supabase"),St(e,`# Supabase Auth
|
|
294
294
|
NEXT_PUBLIC_SUPABASE_URL=
|
|
295
295
|
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=
|
|
296
296
|
NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
|
@@ -298,7 +298,7 @@ SUPABASE_URL=
|
|
|
298
298
|
SUPABASE_PUBLISHABLE_KEY=
|
|
299
299
|
SUPABASE_ANON_KEY=
|
|
300
300
|
SUPABASE_SERVICE_ROLE_KEY=
|
|
301
|
-
`);return}}import
|
|
301
|
+
`);return}}import xe from"fs";import Ce from"path";function Cs(e,t){let n=`// apps/web/src/app/api/auth/callback/${e.id}/route.ts
|
|
302
302
|
// Generated by create-sailor \u2014 OAuth callback for ${e.name}
|
|
303
303
|
// Primary auth provider: ${t}
|
|
304
304
|
// Docs: ${e.docs}`,o={wechat:` const tokenRes = await fetch(
|
|
@@ -423,7 +423,7 @@ ${o[e.id]}
|
|
|
423
423
|
void state;
|
|
424
424
|
return NextResponse.redirect(new URL("/dashboard", req.url));
|
|
425
425
|
}
|
|
426
|
-
`}function
|
|
426
|
+
`}function xs(e){return`"use client";
|
|
427
427
|
|
|
428
428
|
/**
|
|
429
429
|
* SocialLoginButtons \u2014 generated by create-sailor.
|
|
@@ -466,23 +466,23 @@ export function SocialLoginButtons() {
|
|
|
466
466
|
</div>
|
|
467
467
|
);
|
|
468
468
|
}
|
|
469
|
-
`}function Jn(e){
|
|
470
|
-
`+t):
|
|
469
|
+
`}function Jn(e){xe.mkdirSync(e,{recursive:!0})}function Rs(e,t){let n=Ce.join(e,".env.example");xe.existsSync(n)?xe.appendFileSync(n,`
|
|
470
|
+
`+t):xe.writeFileSync(n,t)}function ks(e){let t=`# ${e.name} (${e.id}) \u2014 ${e.docs}`,n=e.envVars.map(o=>`${o}=`).join(`
|
|
471
471
|
`);return`${t}
|
|
472
472
|
${n}
|
|
473
|
-
`}async function Qn(e,t,n){if(!t||t.length===0)return;let o=
|
|
474
|
-
`);ne.appendFileSync(n,a)}function
|
|
473
|
+
`}async function Qn(e,t,n){if(!t||t.length===0)return;let o=Ce.join(e,"apps","web");if(!xe.existsSync(o))return;let r=new Set,s=[];for(let p of t){if(r.has(p))continue;r.add(p);let u=Un(p);u&&s.push(u)}if(s.length===0)return;for(let p of s)Rs(e,ks(p));let i=Ce.join(o,"src","app","api","auth","callback");for(let p of s){let u=Ce.join(i,p.id);Jn(u);let d=Ce.join(u,"route.ts");xe.writeFileSync(d,Cs(p,n))}let a=Ce.join(o,"src","components","auth");Jn(a);let c=Ce.join(a,"SocialLoginButtons.tsx");xe.writeFileSync(c,xs(s))}import Je from"fs";import eo from"path";var Et=[{id:"upstash-redis",name:"Upstash Redis",region:"both",envVars:["UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN"],docs:"https://upstash.com/docs/redis",description:"Serverless Redis"},{id:"vercel-kv",name:"Vercel KV",region:"global",envVars:["KV_URL","KV_REST_API_URL","KV_REST_API_TOKEN","KV_REST_API_READ_ONLY_TOKEN"],docs:"https://vercel.com/docs/storage/vercel-kv",description:"Vercel native KV"},{id:"redis",name:"Redis (self-hosted)",region:"both",envVars:["REDIS_URL"],docs:"https://redis.io/docs/",description:"Self-hosted Redis"},{id:"dragonfly",name:"Dragonfly",region:"global",envVars:["DRAGONFLY_URL"],docs:"https://www.dragonflydb.io/docs",description:"Drop-in Redis replacement, faster"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip cache package"}];function Zn(e){return Et.find(t=>t.id===e)}var Vp=Et.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});import ne from"fs";import vt from"path";function oe(e,t){let n=vt.join(e,".env.example");if(!ne.existsSync(n)||t.envVars.length===0)return;let r=`# ${t.category??t.name}: ${t.name}`;if(ne.readFileSync(n,"utf-8").includes(r))return;let a=["","# =============================================",r,t.docs?`# Docs: ${t.docs}`:null,"# =============================================",...t.envVars.map(c=>`${c}=""`),""].filter(c=>c!==null).join(`
|
|
474
|
+
`);ne.appendFileSync(n,a)}function re(e,t,n){let o=vt.join(e,".env.example");if(!ne.existsSync(o))return;let r=ne.readFileSync(o,"utf-8"),s=`${t}="${n}"`,i=new RegExp(`^${t}=.*$`,"m");if(i.test(r)){ne.writeFileSync(o,r.replace(i,s));return}let a=r.endsWith(`
|
|
475
475
|
`)?"":`
|
|
476
|
-
`;ne.appendFileSync(o,`${a}${
|
|
477
|
-
`)}var
|
|
478
|
-
`);
|
|
479
|
-
`)}async function no(e,t,n){let o=
|
|
476
|
+
`;ne.appendFileSync(o,`${a}${s}
|
|
477
|
+
`)}var Ts=["design","iam","commerce","integrations","platform","ops","ai"];function Re(e,t){for(let o of Ts){let r=vt.join(e,"packages",o,t);if(ne.existsSync(r))return r}let n=vt.join(e,"packages",t);return ne.existsSync(n)?n:null}function z(e,t){let n=Re(e,t);n&&ne.rmSync(n,{recursive:!0,force:!0})}function to(e){return Je.existsSync(e)?Je.readFileSync(e,"utf-8"):null}function Ns(e,t){let n=eo.join(e,".env.example"),o=to(n);if(o===null)return;let r=`# Cache: ${t.name}`;if(o.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
|
|
478
|
+
`);Je.appendFileSync(n,s)}function Os(e,t,n){let o=eo.join(e,".env.example"),r=to(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?Je.writeFileSync(o,r.replace(s,`${t}="${n}"`)):Je.appendFileSync(o,`${t}="${n}"
|
|
479
|
+
`)}async function no(e,t,n){let o=Re(e,"cache");if(t==="none"){o&&Je.rmSync(o,{recursive:!0,force:!0});return}let r=Zn(t);if(!r)throw new Error(`Unknown cache provider "${t}". Valid ids: ${Et.map(s=>s.id).join(", ")}`);o&&(Ns(e,r),Os(e,"CACHE_PROVIDER",t))}var bt=[{id:"turnstile",name:"Cloudflare Turnstile",region:"global",envVars:["NEXT_PUBLIC_TURNSTILE_SITE_KEY","TURNSTILE_SECRET_KEY"],docs:"https://developers.cloudflare.com/turnstile/",description:"Free, privacy-focused captcha alternative"},{id:"hcaptcha",name:"hCaptcha",region:"global",envVars:["NEXT_PUBLIC_HCAPTCHA_SITE_KEY","HCAPTCHA_SECRET_KEY"],docs:"https://docs.hcaptcha.com/",description:"Privacy-respecting captcha"},{id:"aliyun-slide",name:"\u963F\u91CC\u4E91\u9A8C\u8BC1\u7801 2.0",region:"cn",envVars:["ALIYUN_CAPTCHA_ACCESS_KEY_ID","ALIYUN_CAPTCHA_ACCESS_KEY_SECRET","ALIYUN_CAPTCHA_APP_KEY","NEXT_PUBLIC_ALIYUN_CAPTCHA_APP_KEY"],docs:"https://help.aliyun.com/product/28308.html",description:"\u963F\u91CC\u4E91\u667A\u80FD\u9A8C\u8BC1 (\u6ED1\u5757/\u65E0\u75D5)"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function oo(e){return bt.find(t=>t.id===e)}var Jp=bt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function ro(e,t,n="global"){let o=oo(t);if(!o)throw new Error(`Unknown captcha provider "${t}". Valid ids: ${bt.map(r=>r.id).join(", ")}`);if(o.id==="none"){z(e,"captcha");return}o.envVars.length>0&&oe(e,{category:"Captcha",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"CAPTCHA_PROVIDER",o.id)}import Pt from"fs";import Ls from"path";var _t=[{id:"sanity",name:"Sanity",region:"global",envVars:["SANITY_PROJECT_ID","SANITY_DATASET","SANITY_API_TOKEN","SANITY_API_VERSION"],docs:"https://www.sanity.io/docs",description:"Structured content platform with Studio"},{id:"contentful",name:"Contentful",region:"global",envVars:["CONTENTFUL_SPACE_ID","CONTENTFUL_ACCESS_TOKEN","CONTENTFUL_PREVIEW_ACCESS_TOKEN"],docs:"https://www.contentful.com/developers/docs/",description:"Headless CMS"},{id:"strapi",name:"Strapi",region:"both",envVars:["STRAPI_URL","STRAPI_API_TOKEN"],docs:"https://docs.strapi.io",description:"Open-source self-hosted CMS"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function so(e){return _t.find(t=>t.id===e)}var nl=_t.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function io(e,t,n="global"){let o=so(t);if(!o)throw new Error(`Unknown CMS provider "${t}". Valid ids: ${_t.map(s=>s.id).join(", ")}`);let r=Ls.join(e,"apps","studio");if(o.id==="none"){z(e,"sanity"),Pt.existsSync(r)&&Pt.rmSync(r,{recursive:!0,force:!0});return}o.id!=="sanity"&&(z(e,"sanity"),Pt.existsSync(r)&&Pt.rmSync(r,{recursive:!0,force:!0})),o.envVars.length>0&&oe(e,{category:"CMS",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"CMS_PROVIDER",o.id)}import U from"fs";import O from"path";var Us=O.join("apps","web"),rn=O.join("src","components","compliance"),at=O.join("src","app","[locale]");function se(e){return O.join(e,Us)}function Ms(e){U.mkdirSync(e,{recursive:!0})}function J(e,t){Ms(O.dirname(e)),U.writeFileSync(e,t,"utf8")}function sn(e,t){let n=O.join(e,".env.example");if(U.existsSync(n)){if(U.readFileSync(n,"utf8").includes(t.split(`
|
|
480
480
|
`)[0]??""))return;U.appendFileSync(n,`
|
|
481
481
|
`+t+`
|
|
482
482
|
`)}else U.writeFileSync(n,t+`
|
|
483
|
-
`)}var
|
|
483
|
+
`)}var ct=`> **TEMPLATE \u2014 NOT LEGAL ADVICE.** This document is a boilerplate scaffold only.
|
|
484
484
|
> Consult a qualified lawyer in every jurisdiction you operate in before publishing.
|
|
485
|
-
> \u672C\u6587\u6863\u4E3A\u6A21\u677F\u811A\u624B\u67B6\uFF0C\u4E0D\u6784\u6210\u6CD5\u5F8B\u610F\u89C1\u3002\u53D1\u5E03\u524D\u8BF7\u54A8\u8BE2\u76F8\u5173\u53F8\u6CD5\u8F96\u533A\u7684\u5408\u683C\u5F8B\u5E08\u3002`,
|
|
485
|
+
> \u672C\u6587\u6863\u4E3A\u6A21\u677F\u811A\u624B\u67B6\uFF0C\u4E0D\u6784\u6210\u6CD5\u5F8B\u610F\u89C1\u3002\u53D1\u5E03\u524D\u8BF7\u54A8\u8BE2\u76F8\u5173\u53F8\u6CD5\u8F96\u533A\u7684\u5408\u683C\u5F8B\u5E08\u3002`,Ds=`import Link from "next/link";
|
|
486
486
|
import { IcpFooter } from "@/components/compliance/IcpFooter";
|
|
487
487
|
import { PublicSecurityFooter } from "@/components/compliance/PublicSecurityFooter";
|
|
488
488
|
|
|
@@ -533,7 +533,7 @@ export function Footer({ region = "global" }: FooterProps) {
|
|
|
533
533
|
</footer>
|
|
534
534
|
);
|
|
535
535
|
}
|
|
536
|
-
`,
|
|
536
|
+
`,Fs=`export function IcpFooter() {
|
|
537
537
|
const icp = process.env.NEXT_PUBLIC_ICP_BEIAN;
|
|
538
538
|
if (!icp) return null;
|
|
539
539
|
return (
|
|
@@ -547,7 +547,7 @@ export function Footer({ region = "global" }: FooterProps) {
|
|
|
547
547
|
</a>
|
|
548
548
|
);
|
|
549
549
|
}
|
|
550
|
-
`,
|
|
550
|
+
`,js=`export function PublicSecurityFooter() {
|
|
551
551
|
const psb = process.env.NEXT_PUBLIC_PSB_BEIAN;
|
|
552
552
|
const psbCode = process.env.NEXT_PUBLIC_PSB_CODE;
|
|
553
553
|
if (!psb) return null;
|
|
@@ -564,7 +564,7 @@ export function Footer({ region = "global" }: FooterProps) {
|
|
|
564
564
|
</a>
|
|
565
565
|
);
|
|
566
566
|
}
|
|
567
|
-
`,
|
|
567
|
+
`,Bs=`"use client";
|
|
568
568
|
|
|
569
569
|
import { useEffect, useState } from "react";
|
|
570
570
|
|
|
@@ -718,7 +718,7 @@ export function CookieBanner() {
|
|
|
718
718
|
</div>
|
|
719
719
|
);
|
|
720
720
|
}
|
|
721
|
-
`,
|
|
721
|
+
`,Vs=`interface AigcDisclaimerProps {
|
|
722
722
|
className?: string;
|
|
723
723
|
}
|
|
724
724
|
|
|
@@ -738,13 +738,13 @@ export function AigcDisclaimer({ className }: AigcDisclaimerProps) {
|
|
|
738
738
|
</div>
|
|
739
739
|
);
|
|
740
740
|
}
|
|
741
|
-
`,
|
|
741
|
+
`,Ks=`---
|
|
742
742
|
title: Privacy Policy / \u9690\u79C1\u653F\u7B56
|
|
743
743
|
description: How {{COMPANY_NAME}} collects, uses, shares, and protects personal information.
|
|
744
744
|
lastUpdated: 2026-01-01
|
|
745
745
|
---
|
|
746
746
|
|
|
747
|
-
${
|
|
747
|
+
${ct}
|
|
748
748
|
|
|
749
749
|
# Privacy Policy / \u9690\u79C1\u653F\u7B56
|
|
750
750
|
|
|
@@ -883,13 +883,13 @@ or in-app notification before the change takes effect.
|
|
|
883
883
|
**Data Controller / \u6570\u636E\u63A7\u5236\u8005:** {{COMPANY_NAME}}
|
|
884
884
|
**Address / \u5730\u5740:** {{COMPANY_ADDRESS}}
|
|
885
885
|
**Email / \u90AE\u7BB1:** {{COMPANY_CONTACT_EMAIL}}
|
|
886
|
-
`,$
|
|
886
|
+
`,$s=`---
|
|
887
887
|
title: Terms of Service / \u670D\u52A1\u6761\u6B3E
|
|
888
888
|
description: Terms governing your use of {{COMPANY_NAME}}.
|
|
889
889
|
lastUpdated: 2026-01-01
|
|
890
890
|
---
|
|
891
891
|
|
|
892
|
-
${
|
|
892
|
+
${ct}
|
|
893
893
|
|
|
894
894
|
# Terms of Service / \u670D\u52A1\u6761\u6B3E
|
|
895
895
|
|
|
@@ -1002,13 +1002,13 @@ conflict-of-laws principles. Disputes shall be resolved in the competent courts
|
|
|
1002
1002
|
## 11. Contact / \u8054\u7CFB\u65B9\u5F0F
|
|
1003
1003
|
|
|
1004
1004
|
{{COMPANY_NAME}} \xB7 {{COMPANY_ADDRESS}} \xB7 {{COMPANY_CONTACT_EMAIL}}
|
|
1005
|
-
`,
|
|
1005
|
+
`,Ys=`---
|
|
1006
1006
|
title: AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
|
|
1007
1007
|
description: Disclosure required by \u7F51\u4FE1\u529E\u300A\u751F\u6210\u5F0F\u4EBA\u5DE5\u667A\u80FD\u670D\u52A1\u7BA1\u7406\u6682\u884C\u529E\u6CD5\u300B
|
|
1008
1008
|
lastUpdated: 2026-01-01
|
|
1009
1009
|
---
|
|
1010
1010
|
|
|
1011
|
-
${
|
|
1011
|
+
${ct}
|
|
1012
1012
|
|
|
1013
1013
|
# AIGC Disclosure / \u751F\u6210\u5F0F AI \u670D\u52A1\u8BF4\u660E
|
|
1014
1014
|
|
|
@@ -1084,13 +1084,13 @@ human professional.
|
|
|
1084
1084
|
|
|
1085
1085
|
AI \u8F93\u51FA\u53EF\u80FD\u4E0D\u51C6\u786E\u3001\u5B58\u5728\u504F\u89C1\u6216\u8FC7\u65F6\u3002**\u8BF7\u52FF**\u5728\u672A\u7ECF\u5408\u683C\u4E13\u4E1A\u4EBA\u58EB\u72EC\u7ACB\u6838\u5B9E\u7684\u60C5\u51B5\u4E0B\uFF0C\u5C06 AI \u8F93\u51FA
|
|
1086
1086
|
\u7528\u4E8E\u533B\u7597\u3001\u6CD5\u5F8B\u3001\u91D1\u878D\u6216\u5B89\u5168\u6538\u5173\u7684\u51B3\u7B56\u3002
|
|
1087
|
-
`,
|
|
1087
|
+
`,qs=`---
|
|
1088
1088
|
title: Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
|
|
1089
1089
|
description: Notice of cross-border transfer of personal information, per PIPL.
|
|
1090
1090
|
lastUpdated: 2026-01-01
|
|
1091
1091
|
---
|
|
1092
1092
|
|
|
1093
|
-
${
|
|
1093
|
+
${ct}
|
|
1094
1094
|
|
|
1095
1095
|
# Cross-Border Data Notice / \u6570\u636E\u51FA\u5883\u544A\u77E5
|
|
1096
1096
|
|
|
@@ -1149,13 +1149,13 @@ Refusal may limit your ability to use features that rely on overseas services.
|
|
|
1149
1149
|
- \u4F20\u8F93\u4E2D\u52A0\u5BC6 (TLS 1.2+) \u53CA\u9759\u6001\u52A0\u5BC6 (AES-256)\u3002
|
|
1150
1150
|
- \u5408\u540C\u6761\u6B3E\u8981\u6C42\u5883\u5916\u63A5\u6536\u65B9\u63D0\u4F9B\u7B49\u540C\u4E8E PIPL \u7684\u4FDD\u62A4\u3002
|
|
1151
1151
|
- \u8BBF\u95EE\u63A7\u5236\u3001\u5BA1\u8BA1\u65E5\u5FD7\u548C\u8FDD\u89C4\u901A\u77E5\u7A0B\u5E8F\u3002
|
|
1152
|
-
`,
|
|
1152
|
+
`,Gs=`---
|
|
1153
1153
|
title: Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
|
|
1154
1154
|
description: Itemized list of personal information collected, per PIPL Article 17.
|
|
1155
1155
|
lastUpdated: 2026-01-01
|
|
1156
1156
|
---
|
|
1157
1157
|
|
|
1158
|
-
${
|
|
1158
|
+
${ct}
|
|
1159
1159
|
|
|
1160
1160
|
# Personal Information Collection List / \u4E2A\u4EBA\u4FE1\u606F\u6536\u96C6\u6E05\u5355
|
|
1161
1161
|
|
|
@@ -1191,23 +1191,23 @@ To exercise your rights (access, rectify, delete, export, withdraw consent), con
|
|
|
1191
1191
|
**{{COMPANY_CONTACT_EMAIL}}**.
|
|
1192
1192
|
|
|
1193
1193
|
\u5982\u9700\u884C\u4F7F\u60A8\u7684\u6743\u5229\uFF08\u8BBF\u95EE\u3001\u66F4\u6B63\u3001\u5220\u9664\u3001\u5BFC\u51FA\u3001\u64A4\u56DE\u540C\u610F\uFF09\uFF0C\u8BF7\u8054\u7CFB **{{COMPANY_CONTACT_EMAIL}}**\u3002
|
|
1194
|
-
`;async function
|
|
1195
|
-
`))}async function
|
|
1196
|
-
`))}async function
|
|
1197
|
-
`))}async function
|
|
1198
|
-
`))}async function ei(e){let t=
|
|
1199
|
-
`)}import R from"fs";import
|
|
1200
|
-
`+t):R.writeFileSync(n,t)}async function uo(e,t,n){let o=
|
|
1201
|
-
DATABASE_URL="${
|
|
1202
|
-
`),!R.existsSync(
|
|
1194
|
+
`;async function Hs(e,t){let n=se(e);if(!U.existsSync(n))return;let o=O.join(n,"src","components","compliance","Footer.tsx");J(o,Ds);let r=O.join(n,"src","components","compliance","README.md");J(r,["# Compliance Components","",`Auto-generated by \`create-sailor\` for region: \`${t}\`.`,"","## Mounting the Footer","","```tsx",'import { Footer } from "@/components/compliance/Footer";','import { CookieBanner } from "@/components/compliance/CookieBanner";',"","export default function RootLayout({ children }) {"," return ("," <html>"," <body>"," {children}",` <Footer region="${t}" />`," <CookieBanner />"," </body>"," </html>"," );","}","```","","## Placeholders","","Policy MDX files contain `{{COMPANY_NAME}}`, `{{COMPANY_ADDRESS}}`,","`{{COMPANY_CONTACT_EMAIL}}`, `{{GOVERNING_JURISDICTION}}`, and","`{{AIGC_ALGORITHM_FILING_NUMBER}}`. These are filled by the `brand-apply` step.",""].join(`
|
|
1195
|
+
`))}async function Ws(e,t){let n=se(e);if(!U.existsSync(n))return;let o=O.join(n,"src","components","compliance","CookieBanner.tsx");J(o,Bs)}async function Xs(e,t){let n=se(e);if(!U.existsSync(n))return;let o=O.join(n,at,"privacy","page.mdx");J(o,Ks)}async function zs(e,t){let n=se(e);if(!U.existsSync(n))return;let o=O.join(n,at,"terms","page.mdx");J(o,$s)}async function Js(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,rn,"IcpFooter.tsx");J(n,Fs),sn(e,["# Chinese ICP filing (\u5DE5\u4FE1\u90E8 ICP \u5907\u6848) \u2014 required to legally host a","# public-facing site from mainland China. Apply at https://beian.miit.gov.cn/",'NEXT_PUBLIC_ICP_BEIAN="" # \u5982 \u82CFICP\u59072024XXXXXX\u53F7'].join(`
|
|
1196
|
+
`))}async function Qs(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,rn,"PublicSecurityFooter.tsx");J(n,js),sn(e,["# Chinese Public Security Bureau filing (\u516C\u5B89\u8054\u7F51\u5907\u6848)","# Required in addition to ICP. Apply at http://www.beian.gov.cn/",'NEXT_PUBLIC_PSB_BEIAN="" # \u5982 \u82CF\u516C\u7F51\u5B89\u5907 32011402XXXXXX\u53F7','NEXT_PUBLIC_PSB_CODE="" # 14-digit record code'].join(`
|
|
1197
|
+
`))}async function Zs(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,rn,"AigcDisclaimer.tsx");J(n,Vs),sn(e,["# Generative AI algorithm filing (\u7B97\u6CD5\u5907\u6848\u53F7) \u2014 required by","# \u7F51\u4FE1\u529E\u300A\u751F\u6210\u5F0F\u4EBA\u5DE5\u667A\u80FD\u670D\u52A1\u7BA1\u7406\u6682\u884C\u529E\u6CD5\u300Bfor services offered in China.",'NEXT_PUBLIC_AIGC_FILING_NUMBER="" # e.g. \u7F51\u4FE1\u7B97\u5907XXXXXXXX\u53F7'].join(`
|
|
1198
|
+
`))}async function ei(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,at,"aigc-disclosure","page.mdx");J(n,Ys)}async function ti(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,at,"cross-border-data","page.mdx");J(n,qs)}async function ni(e){let t=se(e);if(!U.existsSync(t))return;let n=O.join(t,at,"pii-collection","page.mdx");J(n,Gs)}async function ao(e,t){try{await Hs(e,t),await Ws(e,t),await Xs(e,t),await zs(e,t),(t==="cn"||t==="hybrid")&&(await Js(e),await Qs(e),await Zs(e),await ei(e),await ti(e),await ni(e))}catch(n){throw console.error("applyComplianceTemplates failed:",n),new Error(`Failed to apply compliance templates for region "${t}". Check that ${e} is writable.`)}}import oi from"fs";import ri from"path";async function co(e,t){let n=ri.join(e,"nebutra.config.json");oi.writeFileSync(n,JSON.stringify(t,null,2)+`
|
|
1199
|
+
`)}import R from"fs";import ke from"path";function si(e){R.existsSync(e)&&R.rmSync(e,{recursive:!0,force:!0})}function po(e,t){return e.replace(/provider\s*=\s*"postgresql"/,`provider = "${t}"`)}function ii(e){return e.replace(/^\s*directUrl\s*=\s*env\([^)]*\)\s*\n/gm,"")}function lo(e){let t=e.replace(/^\s*extensions\s*=\s*\[[^\]]*\]\s*\n/gm,"");return t=t.replace(/previewFeatures\s*=\s*\[\s*"postgresqlExtensions"\s*\]\s*\n/g,""),t}function ai(e,t){let n=ke.join(e,".env.example");R.existsSync(n)?R.appendFileSync(n,`
|
|
1200
|
+
`+t):R.writeFileSync(n,t)}async function uo(e,t,n){let o=ke.join(e,"packages","platform","db");if(t==="none"){si(o);return}let r=ke.join(o,"prisma","schema.prisma"),s;if(t==="postgresql"?s=`postgresql://postgres:postgres@localhost:5432/${n}`:t==="mysql"?s=`mysql://root:root@localhost:3306/${n}`:s="file:./dev.db",ai(e,`# Database (${t})
|
|
1201
|
+
DATABASE_URL="${s}"
|
|
1202
|
+
`),!R.existsSync(r))return;let i=R.readFileSync(r,"utf8"),a=i;t==="mysql"?(a=po(a,"mysql"),a=lo(a)):t==="sqlite"&&(a=po(a,"sqlite"),a=ii(a),a=lo(a)),a!==i&&R.writeFileSync(r,a)}function ci(e){let t=ke.join(e,".env.example");return R.existsSync(t)?R.readFileSync(t,"utf8"):""}function pi(e,t,n,o){let r=ke.join(e,".env.example"),s=ci(e),i=o?`# ${o}
|
|
1203
1203
|
${t}="${n}"
|
|
1204
1204
|
`:`${t}="${n}"
|
|
1205
|
-
`,a=new RegExp(`^\\s*${t}\\s*=.*$`,"m");if(a.test(
|
|
1206
|
-
${i}`):R.writeFileSync(
|
|
1207
|
-
`),c=o.replace(
|
|
1208
|
-
${a}$2`);R.writeFileSync(n,c)}function di(e){let t=
|
|
1209
|
-
`))}async function mo(e,t,n){if(!(t.id==="none"||t.id==="local")){for(let o of t.envVars){let
|
|
1210
|
-
`+t):
|
|
1205
|
+
`,a=new RegExp(`^\\s*${t}\\s*=.*$`,"m");if(a.test(s)){R.writeFileSync(r,s.replace(a,`${t}="${n}"`));return}s?R.appendFileSync(r,`
|
|
1206
|
+
${i}`):R.writeFileSync(r,i)}function li(e,t){let n=ke.join(e,"packages","platform","db","prisma","schema.prisma");if(!R.existsSync(n))return;let o=R.readFileSync(n,"utf8"),r=/(datasource\s+db\s*\{[^}]*?)(\n})/;if(!o.match(r))return;let i=t.filter(p=>!o.includes(p.trim()));if(i.length===0)return;let a=i.map(p=>` ${p}`).join(`
|
|
1207
|
+
`),c=o.replace(r,`$1
|
|
1208
|
+
${a}$2`);R.writeFileSync(n,c)}function di(e){let t=ke.join(e,"packages","platform","db","prisma","schema.prisma");if(!R.existsSync(t))return;let n=R.readFileSync(t,"utf8");if(/directUrl\s*=\s*env\(/.test(n))return;let o=/(datasource\s+db\s*\{[\s\S]*?url\s*=\s*env\(\s*"DATABASE_URL"\s*\)[^\n]*\n)/;o.test(n)&&R.writeFileSync(t,n.replace(o,`$1 directUrl = env("DIRECT_URL")
|
|
1209
|
+
`))}async function mo(e,t,n){if(!(t.id==="none"||t.id==="local")){for(let o of t.envVars){let r=o.placeholder.replace(/\$PROJECT/g,n);pi(e,o.name,r,o.comment)}t.prismaDatasourceExtras&&t.prismaDatasourceExtras.length>0&&li(e,t.prismaDatasourceExtras),t.keepDirectUrl&&di(e)}}import ve from"fs";import Te from"path";import{fileURLToPath as ui}from"url";var mi=ui(import.meta.url),go=Te.dirname(mi),gi=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|vue)$/,fo=["fumadocs","nextra","mintlify","docusaurus","vitepress"];function fi(e){let t=[Te.join(go,"..","templates","docs",e),Te.join(go,"..","..","templates","docs",e)];for(let n of t)if(ve.existsSync(n))return n;return t[0]}async function yo(e,t){if(t.framework==="none")return;if(!fo.includes(t.framework))throw new Error(`Unsupported docs framework: "${t.framework}". Supported: ${fo.join(", ")}, none.`);let n=fi(t.framework),o=Te.join(e,"apps","docs");if(!ve.existsSync(n))throw new Error(`Docs template not found: ${n}`);So(n,o),ho(o,{"{PRODUCT_NAME}":t.projectName})}function So(e,t){ve.mkdirSync(t,{recursive:!0});for(let n of ve.readdirSync(e,{withFileTypes:!0})){let o=Te.join(e,n.name),r=Te.join(t,n.name);n.isDirectory()?So(o,r):ve.copyFileSync(o,r)}}function ho(e,t){for(let n of ve.readdirSync(e,{withFileTypes:!0})){let o=Te.join(e,n.name);if(n.isDirectory())ho(o,t);else if(gi.test(n.name)){let r=ve.readFileSync(o,"utf-8");for(let[s,i]of Object.entries(t))r=r.split(s).join(i);ve.writeFileSync(o,r)}}}import Oe from"fs";import Ne from"path";var wt=[{id:"resend",name:"Resend",region:"global",envVars:["RESEND_API_KEY","RESEND_FROM"],docs:"https://resend.com/docs",pkg:"resend",pkgVersion:"^4.0.1"},{id:"postmark",name:"Postmark",region:"global",envVars:["POSTMARK_API_KEY","POSTMARK_FROM"],docs:"https://postmarkapp.com/developer",pkg:"postmark",pkgVersion:"^4.0.5"},{id:"ses",name:"AWS SES",region:"global",envVars:["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_SES_REGION","SES_FROM"],docs:"https://docs.aws.amazon.com/ses",pkg:"@aws-sdk/client-sesv2",pkgVersion:"^3.658.0"},{id:"aliyun-dm",name:"\u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001",region:"cn",envVars:["ALIYUN_DM_ACCESS_KEY","ALIYUN_DM_ACCESS_SECRET","ALIYUN_DM_ACCOUNT_NAME","ALIYUN_DM_FROM_ALIAS"],docs:"https://help.aliyun.com/product/29412.html",pkg:"@alicloud/dm20151123",pkgVersion:"^3.0.0"},{id:"tencent-ses",name:"\u817E\u8BAF\u4E91 SES",region:"cn",envVars:["TENCENT_SECRET_ID","TENCENT_SECRET_KEY","TENCENT_SES_FROM_EMAIL"],docs:"https://cloud.tencent.com/document/product/1288",pkg:"tencentcloud-sdk-nodejs-ses",pkgVersion:"^4.0.900"},{id:"netease",name:"\u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1",region:"cn",envVars:["NETEASE_USER","NETEASE_PASS","NETEASE_FROM"],docs:"https://qiye.163.com/help",pkg:"nodemailer",pkgVersion:"^6.9.15"},{id:"none",name:"None",region:"global",envVars:[],docs:""}];function Eo(e){return wt.find(t=>t.id===e)}var Pl=wt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});var Le="@nebutra/email";function an(e,t){Oe.mkdirSync(Ne.dirname(e),{recursive:!0}),Oe.writeFileSync(e,t)}function yi(e,t){let n=Ne.join(e,".env.example");Oe.existsSync(n)?Oe.appendFileSync(n,`
|
|
1210
|
+
`+t):Oe.writeFileSync(n,t)}function Si(e){if(e.envVars.length===0)return"";let t=`# Email provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
|
|
1211
1211
|
`);return`${t}
|
|
1212
1212
|
${n}
|
|
1213
1213
|
`}var hi=`/**
|
|
@@ -1231,7 +1231,7 @@ export interface SendEmailResult {
|
|
|
1231
1231
|
raw?: unknown;
|
|
1232
1232
|
}
|
|
1233
1233
|
`;function Ei(){return`/**
|
|
1234
|
-
* @${
|
|
1234
|
+
* @${Le.slice(1)} \u2014 Resend transactional email wrapper.
|
|
1235
1235
|
*
|
|
1236
1236
|
* Docs: https://resend.com/docs
|
|
1237
1237
|
*/
|
|
@@ -1270,7 +1270,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
|
|
|
1270
1270
|
|
|
1271
1271
|
export type { SendEmailInput, SendEmailResult } from "./types";
|
|
1272
1272
|
`}function vi(){return`/**
|
|
1273
|
-
* @${
|
|
1273
|
+
* @${Le.slice(1)} \u2014 Postmark transactional email wrapper.
|
|
1274
1274
|
*
|
|
1275
1275
|
* Docs: https://postmarkapp.com/developer
|
|
1276
1276
|
*/
|
|
@@ -1308,7 +1308,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
|
|
|
1308
1308
|
|
|
1309
1309
|
export type { SendEmailInput, SendEmailResult } from "./types";
|
|
1310
1310
|
`}function bi(){return`/**
|
|
1311
|
-
* @${
|
|
1311
|
+
* @${Le.slice(1)} \u2014 AWS SES v2 transactional email wrapper.
|
|
1312
1312
|
*
|
|
1313
1313
|
* Docs: https://docs.aws.amazon.com/ses
|
|
1314
1314
|
*/
|
|
@@ -1364,7 +1364,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
|
|
|
1364
1364
|
|
|
1365
1365
|
export type { SendEmailInput, SendEmailResult } from "./types";
|
|
1366
1366
|
`}function _i(){return`/**
|
|
1367
|
-
* @${
|
|
1367
|
+
* @${Le.slice(1)} \u2014 \u963F\u91CC\u4E91\u90AE\u4EF6\u63A8\u9001 (Aliyun DirectMail) wrapper.
|
|
1368
1368
|
*
|
|
1369
1369
|
* Docs: https://help.aliyun.com/product/29412.html
|
|
1370
1370
|
*/
|
|
@@ -1414,7 +1414,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
|
|
|
1414
1414
|
|
|
1415
1415
|
export type { SendEmailInput, SendEmailResult } from "./types";
|
|
1416
1416
|
`}function Pi(){return`/**
|
|
1417
|
-
* @${
|
|
1417
|
+
* @${Le.slice(1)} \u2014 \u817E\u8BAF\u4E91 SES wrapper.
|
|
1418
1418
|
*
|
|
1419
1419
|
* Docs: https://cloud.tencent.com/document/product/1288
|
|
1420
1420
|
*/
|
|
@@ -1462,7 +1462,7 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
|
|
|
1462
1462
|
|
|
1463
1463
|
export type { SendEmailInput, SendEmailResult } from "./types";
|
|
1464
1464
|
`}function wi(){return`/**
|
|
1465
|
-
* @${
|
|
1465
|
+
* @${Le.slice(1)} \u2014 \u7F51\u6613\u4F01\u4E1A\u90AE\u7BB1 via SMTP (nodemailer).
|
|
1466
1466
|
*
|
|
1467
1467
|
* Docs: https://qiye.163.com/help
|
|
1468
1468
|
*/
|
|
@@ -1500,32 +1500,31 @@ export async function sendEmail(input: SendEmailInput): Promise<SendEmailResult>
|
|
|
1500
1500
|
|
|
1501
1501
|
export type { SendEmailInput, SendEmailResult } from "./types";
|
|
1502
1502
|
`}function Ai(e){switch(e){case"resend":return Ei();case"postmark":return vi();case"ses":return bi();case"aliyun-dm":return _i();case"tencent-ses":return Pi();case"netease":return wi();case"none":return`export {};
|
|
1503
|
-
`}}function Ii(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),e.id==="aliyun-dm"&&(t["@alicloud/openapi-client"]="^0.4.12");let n={name:
|
|
1504
|
-
`}async function vo(e,t,n){if(t==="none")return;let o=Eo(t);if(!o)throw new Error(`Unknown email provider "${t}". Valid ids: ${
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
`+n)}import wo from"crypto";import ct from"fs";import Po from"path";function Le(e){return wo.randomBytes(e).toString("base64").replace(/=+$/,"")}function Ci(e){return wo.randomBytes(e).toString("hex")}function xi(){return{AUTH_SECRET:Le(32),NEXTAUTH_SECRET:Le(32),BETTER_AUTH_SECRET:Le(32),JWT_SECRET:Le(32),WEBHOOK_SECRET:Ci(16),ENCRYPTION_KEY:Le(32),API_SECRET_KEY:Le(32),SESSION_SECRET:Le(32)}}function Ri(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function ki(e,t,n){let o=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),s=Ri(n);return e.replace(o,`${t}="${s}"`)}async function Ao(e){let t=Po.join(e,".env.example"),n=Po.join(e,".env.local");if(!ct.existsSync(t))return null;try{let o=ct.readFileSync(t,"utf8"),s=xi(),i=ct.existsSync(n)?ct.readFileSync(n,"utf8"):o;for(let a of Object.keys(s))i=ki(i,a,s[a]);return ct.writeFileSync(n,i),s}catch(o){let s=o instanceof Error?o.message:String(o);throw console.error(`[create-sailor] Failed to generate env secrets: ${s}`),new Error(`Unable to write .env.local: ${s}`)}}var At=[{id:"vercel-flags",name:"Vercel Flags SDK",region:"global",envVars:["FLAGS_SECRET"],docs:"https://vercel.com/docs/workflow-collaboration/feature-flags",description:"Native Vercel feature flags"},{id:"growthbook",name:"GrowthBook",region:"both",envVars:["GROWTHBOOK_API_HOST","GROWTHBOOK_CLIENT_KEY","GROWTHBOOK_DECRYPTION_KEY"],docs:"https://docs.growthbook.io",description:"Open-source A/B testing + flags"},{id:"configcat",name:"ConfigCat",region:"global",envVars:["CONFIGCAT_SDK_KEY"],docs:"https://configcat.com/docs/",description:"Feature flag & config management"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Io(e){return At.find(t=>t.id===e)}var Ll=At.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Co(e,t,n="global"){let o=Io(t);if(!o)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${At.map(s=>s.id).join(", ")}`);if(o.id==="none"){z(e,"feature-flags");return}o.envVars.length>0&&oe(e,{category:"Feature Flags",name:o.name,envVars:o.envVars,docs:o.docs}),se(e,"FEATURE_FLAGS_PROVIDER",o.id)}import{execFileSync as To}from"child_process";import L from"fs";import Ti from"os";import ie from"path";import Ni from"ignore";var Oi={mirror:{repo:process.env.SAILOR_TEMPLATE_REPO||"Nebutra/Sailor-Template",ref:process.env.SAILOR_TEMPLATE_REF||"main",applyIgnore:!1,allowMutableFallback:process.env.SAILOR_TEMPLATE_ALLOW_MUTABLE_FALLBACK==="1"},main:{repo:"Nebutra/Nebutra-Sailor",ref:"main",applyIgnore:!0,allowMutableFallback:process.env.SAILOR_TEMPLATE_ALLOW_MUTABLE_FALLBACK==="1"}};function Li(){let e=process.env.SAILOR_TEMPLATE_LOCAL_DIR;if(!(!e||e.trim().length===0))return ie.resolve(e.trim())}var Ui=new Set(["node_modules",".git","dist",".next",".turbo"]);function Mi(e,t){if(!L.statSync(e).isDirectory())throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR is not a directory: ${e}`);L.cpSync(e,t,{recursive:!0,dereference:!0,filter:o=>{let s=ie.basename(o);return!Ui.has(s)}})}function Di(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function Fi(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function No(e){return/^[0-9a-f]{7,40}$/i.test(e)}function ji(e,t){let n=`https://github.com/${e}.git`,o=[`refs/heads/${t}`,`refs/tags/${t}`];for(let s of o)try{let r=To("git",["ls-remote",n,s],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!r)continue;let[i]=r.split(/\s+/);if(No(i))return i}catch{}return null}async function Bi(e,t){if(No(t))return t;let n=await fetch(`https://api.github.com/repos/${e}/commits/${encodeURIComponent(t)}`,{headers:{Accept:"application/vnd.github+json","User-Agent":"create-sailor"}});if(!n.ok){let s=ji(e,t);if(s)return s;throw new Error(`Failed to resolve ${e}@${t} (GitHub API ${n.status})`)}let o=await n.json();if(typeof o.sha!="string"||o.sha.length===0)throw new Error(`GitHub API did not return a commit SHA for ${e}@${t}`);return o.sha}function Oo(e,t,n){let o=L.readdirSync(t,{withFileTypes:!0});for(let s of o){if(s.name==="node_modules"||s.name===".git")continue;let r=ie.join(t,s.name),i=ie.relative(e,r).split(ie.sep).join("/");s.isDirectory()?(n.push(i+"/"),Oo(e,r,n)):n.push(i)}}function xo(e){let t=ie.join(e,".templateignore");if(!L.existsSync(t))return;let n=L.readFileSync(t,"utf8"),o=Ni().add(n),s=[];Oo(e,e,s);let r=s.map(c=>c.endsWith("/")?c.slice(0,-1):c),i=new Set(o.filter(r)),a=r.filter(c=>!i.has(c)).sort((c,l)=>l.split("/").length-c.split("/").length);for(let c of a){let l=ie.join(e,c);try{L.existsSync(l)&&L.rmSync(l,{recursive:!0,force:!0})}catch{}}try{L.existsSync(t)&&L.rmSync(t,{force:!0})}catch{}}async function Ro(e,t){let n=await fetch(e,{headers:{Accept:"application/octet-stream","User-Agent":"create-sailor"}});if(!n.ok)throw new Error(`Failed to download archive (${n.status})`);let o=Buffer.from(await n.arrayBuffer());if(o.byteLength<1024)throw new Error(`Downloaded archive is unexpectedly small (${o.byteLength} bytes)`);L.writeFileSync(t,o);let s=L.statSync(t);if(s.size!==o.byteLength)throw new Error(`Archive write verification failed (${s.size} != ${o.byteLength})`);return s.size}function ko(e,t){To("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function cn(e){try{let t=L.readdirSync(e);for(let n of t)L.rmSync(ie.join(e,n),{recursive:!0,force:!0})}catch{}}async function Vi(e,t){let n=L.mkdtempSync(ie.join(Ti.tmpdir(),"create-sailor-")),o=ie.join(n,"template.tar.gz");try{let s=await Bi(e.repo,e.ref);await Ro(Fi(e.repo,s),o),ko(o,t)}catch(s){if(!e.allowMutableFallback)throw s;cn(t),await Ro(Di(e.repo,e.ref),o),ko(o,t)}finally{L.rmSync(n,{recursive:!0,force:!0})}}async function Lo(e){L.mkdirSync(e,{recursive:!0});let t=Li();if(t){if(!L.existsSync(t))throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR does not exist: ${t}`);cn(e),Mi(t,e);try{xo(e)}catch(r){throw new Error(`Local template copied, but .templateignore processing failed: ${r instanceof Error?r.message:String(r)}`)}return}let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],s;for(let r of o){let i=Oi[r];try{if(await Vi(i,e),i.applyIgnore)try{xo(e)}catch(a){throw new Error(`Template cloned, but .templateignore processing failed: ${a instanceof Error?a.message:String(a)}`)}return}catch(a){s=a instanceof Error?a:new Error(String(a)),cn(e)}}throw new Error(`Failed to download the template from any source. Last error: ${s?.message??"unknown"}
|
|
1503
|
+
`}}function Ii(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),e.id==="aliyun-dm"&&(t["@alicloud/openapi-client"]="^0.4.12");let n={name:Le,version:"0.1.0",private:!0,description:`Transactional email via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
|
|
1504
|
+
`}async function vo(e,t,n){if(t==="none")return;let o=Eo(t);if(!o)throw new Error(`Unknown email provider "${t}". Valid ids: ${wt.map(i=>i.id).join(", ")}`);let r=Ne.join(e,"packages","email"),s=Ne.join(r,"src");Oe.existsSync(s)&&Oe.rmSync(s,{recursive:!0,force:!0}),an(Ne.join(r,"package.json"),Ii(o)),an(Ne.join(s,"types.ts"),hi),an(Ne.join(s,"index.ts"),Ai(o.id)),yi(e,Si(o))}import be from"fs";import bo from"path";function Ci(e,t){return new RegExp(`^\\s*${t}\\s*=`,"m").test(e)}function xi(e){return e.endsWith(`
|
|
1505
|
+
`)?e:`${e}
|
|
1506
|
+
`}async function _o(e,t){let n=bo.join(e,".env"),o=bo.join(e,".env.local"),r=be.existsSync(n)?be.readFileSync(n,"utf8"):"",s=be.existsSync(o)?be.readFileSync(o,"utf8"):"",i=`${r}
|
|
1507
|
+
${s}`,a=[{name:"DATABASE_URL",value:String(t.databaseUrl)},{name:"NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY",value:String(t.clerkPublishable)},{name:"CLERK_SECRET_KEY",value:String(t.clerkSecret)},{name:"NEXT_PUBLIC_SITE_URL",value:"http://localhost:3000"}].filter(p=>!Ci(i,p.name)).map(p=>`${p.name}="${p.value}"`);if(a.length===0)return;let c=`# Automatically injected by create-sailor
|
|
1508
|
+
${a.join(`
|
|
1509
|
+
`)}
|
|
1510
|
+
`;if(!be.existsSync(n)&&!be.existsSync(o))be.writeFileSync(o,c);else{let p=s?xi(s):"";be.writeFileSync(o,`${p}
|
|
1511
|
+
${c}`)}}import wo from"crypto";import pt from"fs";import Po from"path";function Ue(e){return wo.randomBytes(e).toString("base64").replace(/=+$/,"")}function Ri(e){return wo.randomBytes(e).toString("hex")}function ki(){return{AUTH_SECRET:Ue(32),NEXTAUTH_SECRET:Ue(32),BETTER_AUTH_SECRET:Ue(32),JWT_SECRET:Ue(32),WEBHOOK_SECRET:Ri(16),ENCRYPTION_KEY:Ue(32),API_SECRET_KEY:Ue(32),SESSION_SECRET:Ue(32)}}function Ti(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Ni(e,t,n){let o=new RegExp(`^(?!#)\\s*${t}=.*$`,"gm"),r=Ti(n);return e.replace(o,`${t}="${r}"`)}async function Ao(e){let t=Po.join(e,".env.example"),n=Po.join(e,".env.local");if(!pt.existsSync(t))return null;try{let o=pt.readFileSync(t,"utf8"),r=ki(),i=pt.existsSync(n)?pt.readFileSync(n,"utf8"):o;for(let a of Object.keys(r))i=Ni(i,a,r[a]);return pt.writeFileSync(n,i),r}catch(o){let r=o instanceof Error?o.message:String(o);throw console.error(`[create-sailor] Failed to generate env secrets: ${r}`),new Error(`Unable to write .env.local: ${r}`)}}var At=[{id:"vercel-flags",name:"Vercel Flags SDK",region:"global",envVars:["FLAGS_SECRET"],docs:"https://vercel.com/docs/workflow-collaboration/feature-flags",description:"Native Vercel feature flags"},{id:"growthbook",name:"GrowthBook",region:"both",envVars:["GROWTHBOOK_API_HOST","GROWTHBOOK_CLIENT_KEY","GROWTHBOOK_DECRYPTION_KEY"],docs:"https://docs.growthbook.io",description:"Open-source A/B testing + flags"},{id:"configcat",name:"ConfigCat",region:"global",envVars:["CONFIGCAT_SDK_KEY"],docs:"https://configcat.com/docs/",description:"Feature flag & config management"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Io(e){return At.find(t=>t.id===e)}var Ml=At.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Co(e,t,n="global"){let o=Io(t);if(!o)throw new Error(`Unknown feature-flags provider "${t}". Valid ids: ${At.map(r=>r.id).join(", ")}`);if(o.id==="none"){z(e,"feature-flags");return}o.envVars.length>0&&oe(e,{category:"Feature Flags",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"FEATURE_FLAGS_PROVIDER",o.id)}import{execFileSync as To}from"child_process";import L from"fs";import Oi from"os";import ie from"path";import Li from"ignore";var Ui={mirror:{repo:process.env.SAILOR_TEMPLATE_REPO||"Nebutra/Sailor-Template",ref:process.env.SAILOR_TEMPLATE_REF||"main",applyIgnore:!1,allowMutableFallback:process.env.SAILOR_TEMPLATE_ALLOW_MUTABLE_FALLBACK==="1"},main:{repo:"Nebutra/Nebutra-Sailor",ref:"main",applyIgnore:!0,allowMutableFallback:process.env.SAILOR_TEMPLATE_ALLOW_MUTABLE_FALLBACK==="1"}};function Mi(){let e=process.env.SAILOR_TEMPLATE_LOCAL_DIR;if(!(!e||e.trim().length===0))return ie.resolve(e.trim())}var Di=new Set(["node_modules",".git","dist",".next",".turbo"]);function Fi(e,t){if(!L.statSync(e).isDirectory())throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR is not a directory: ${e}`);L.cpSync(e,t,{recursive:!0,dereference:!0,filter:o=>{let r=ie.basename(o);return!Di.has(r)}})}function ji(e,t){return`https://github.com/${e}/archive/refs/heads/${t}.tar.gz`}function Bi(e,t){return`https://github.com/${e}/archive/${t}.tar.gz`}function No(e){return/^[0-9a-f]{7,40}$/i.test(e)}function Vi(e,t){let n=`https://github.com/${e}.git`,o=[`refs/heads/${t}`,`refs/tags/${t}`];for(let r of o)try{let s=To("git",["ls-remote",n,r],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!s)continue;let[i]=s.split(/\s+/);if(No(i))return i}catch{}return null}async function Ki(e,t){if(No(t))return t;let n=await fetch(`https://api.github.com/repos/${e}/commits/${encodeURIComponent(t)}`,{headers:{Accept:"application/vnd.github+json","User-Agent":"create-sailor"}});if(!n.ok){let r=Vi(e,t);if(r)return r;throw new Error(`Failed to resolve ${e}@${t} (GitHub API ${n.status})`)}let o=await n.json();if(typeof o.sha!="string"||o.sha.length===0)throw new Error(`GitHub API did not return a commit SHA for ${e}@${t}`);return o.sha}function Oo(e,t,n){let o=L.readdirSync(t,{withFileTypes:!0});for(let r of o){if(r.name==="node_modules"||r.name===".git")continue;let s=ie.join(t,r.name),i=ie.relative(e,s).split(ie.sep).join("/");r.isDirectory()?(n.push(i+"/"),Oo(e,s,n)):n.push(i)}}function xo(e){let t=ie.join(e,".templateignore");if(!L.existsSync(t))return;let n=L.readFileSync(t,"utf8"),o=Li().add(n),r=[];Oo(e,e,r);let s=r.map(c=>c.endsWith("/")?c.slice(0,-1):c),i=new Set(o.filter(s)),a=s.filter(c=>!i.has(c)).sort((c,p)=>p.split("/").length-c.split("/").length);for(let c of a){let p=ie.join(e,c);try{L.existsSync(p)&&L.rmSync(p,{recursive:!0,force:!0})}catch{}}try{L.existsSync(t)&&L.rmSync(t,{force:!0})}catch{}}async function Ro(e,t){let n=await fetch(e,{headers:{Accept:"application/octet-stream","User-Agent":"create-sailor"}});if(!n.ok)throw new Error(`Failed to download archive (${n.status})`);let o=Buffer.from(await n.arrayBuffer());if(o.byteLength<1024)throw new Error(`Downloaded archive is unexpectedly small (${o.byteLength} bytes)`);L.writeFileSync(t,o);let r=L.statSync(t);if(r.size!==o.byteLength)throw new Error(`Archive write verification failed (${r.size} != ${o.byteLength})`);return r.size}function ko(e,t){To("tar",["-xzf",e,"-C",t,"--strip-components=1"],{stdio:"ignore"})}function cn(e){try{let t=L.readdirSync(e);for(let n of t)L.rmSync(ie.join(e,n),{recursive:!0,force:!0})}catch{}}async function $i(e,t){let n=L.mkdtempSync(ie.join(Oi.tmpdir(),"create-sailor-")),o=ie.join(n,"template.tar.gz");try{let r=await Ki(e.repo,e.ref);await Ro(Bi(e.repo,r),o),ko(o,t)}catch(r){if(!e.allowMutableFallback)throw r;cn(t),await Ro(ji(e.repo,e.ref),o),ko(o,t)}finally{L.rmSync(n,{recursive:!0,force:!0})}}async function Lo(e){L.mkdirSync(e,{recursive:!0});let t=Mi();if(t){if(!L.existsSync(t))throw new Error(`SAILOR_TEMPLATE_LOCAL_DIR does not exist: ${t}`);cn(e),Fi(t,e);try{xo(e)}catch(s){throw new Error(`Local template copied, but .templateignore processing failed: ${s instanceof Error?s.message:String(s)}`)}return}let o=process.env.SAILOR_TEMPLATE_SOURCE==="main"?["main"]:["mirror","main"],r;for(let s of o){let i=Ui[s];try{if(await $i(i,e),i.applyIgnore)try{xo(e)}catch(a){throw new Error(`Template cloned, but .templateignore processing failed: ${a instanceof Error?a.message:String(a)}`)}return}catch(a){r=a instanceof Error?a:new Error(String(a)),cn(e)}}throw new Error(`Failed to download the template from any source. Last error: ${r?.message??"unknown"}
|
|
1513
1512
|
|
|
1514
1513
|
Ensure you have internet access and 'tar' installed.
|
|
1515
|
-
You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import It from"fs";import pn from"path";var
|
|
1516
|
-
`);let a=pn.join(e,"package.json"),c;try{c=It.readFileSync(a,"utf8")}catch(
|
|
1517
|
-
`)}return{lints:o,configWritten:!0}}import{createHmac as
|
|
1514
|
+
You can override the source with SAILOR_TEMPLATE_REPO / SAILOR_TEMPLATE_REF env vars.`)}import It from"fs";import pn from"path";var Yi="node scripts/governance/lint-no-raw-inputs.mjs",qi="node scripts/governance/lint-repository-seam.mjs",Gi="node scripts/governance/lint-brand-literals.mjs",Hi="node scripts/governance/lint-microcopy.mjs",Wi=/\bnode\s+scripts\/(governance\/)?lint-[\w-]+\.mjs/g,Xi=/\bnode\s+scripts\/lint-[\w-]+\.mjs/,zi={scanRoots:["apps"],primitivesImport:"@nebutra/ui/primitives",whitelist:["/storybook/src/stories/","/design-docs/src/components/previews/","/sailor-docs/src/components/previews/","\\.test\\.tsx?$","/__tests__/"]},Ji={coreDomains:["^packages/.*/(billing|license|metering|auth|audit|permissions|identity|tenant)/","^backends/gateway/src/routes/(billing|ai|admin|legal|integrations|webhooks)/","^apps/web/src/app/api/"],seamPaths:["^packages/platform/repositories/","^packages/platform/db/"],dbAccessors:["getTenantDb","getSystemDb"],allowlist:["apps/web/src/app/api/invitations/[invitationId]/accept/route.ts","apps/web/src/app/api/onboarding/invite-members/route.ts","apps/web/src/app/api/startup-os/projects/[projectId]/runs/[runId]/execute/route.ts","apps/web/src/app/api/cofounder/room/[profileId]/form-team/route.ts","apps/web/src/app/api/provider-keys/route.ts","backends/gateway/src/routes/admin/index.ts","backends/gateway/src/routes/ai/api-keys.ts","backends/gateway/src/routes/ai/usage.ts","backends/gateway/src/routes/billing/index.ts","backends/gateway/src/routes/integrations/index.ts","backends/gateway/src/routes/legal/consent.ts","backends/gateway/src/routes/webhooks/clerk.ts","backends/gateway/src/routes/webhooks/stripe.ts","packages/commerce/license/src/issue-license.ts","packages/commerce/license/src/validate-license.ts","packages/commerce/billing/src/credits/service.ts","packages/commerce/billing/src/usage/ledger.ts","packages/iam/audit/src/index.ts","packages/iam/auth/src/plugins/passkey-plugin.ts"]},Qi={scanRoots:["apps/web/src"],excludePaths:["/api/","\\.test\\.tsx?$","/__tests__/","/storybook/src/stories/","/design-docs/","/sailor-docs/"],bannedPatterns:[],allowlist:[]},Uo={governedPaths:["apps","packages/commerce","packages/integrations/email"],allowExpressions:["Nebutra","\u4E91\u6BD3\u667A\u80FD","\u4E91\u6BD3","nebutra\\.com","nebutra\\.ai","#0033FE","#0BF1C3"],knownExemptPatterns:["\\.stories\\.tsx?$","/__tests__/","\\.test\\.tsx?$","/previews/","^packages/design/brand/","^packages/design/tokens/","^packages/design/design-tokens/"],allowlist:[]},Zi=["apps/design-docs/mdx-components.tsx","apps/design-docs/next.config.ts","apps/design-docs/src/__registry__/index.tsx","apps/design-docs/src/app/[lang]/docs/[[...slug]]/page.tsx","apps/design-docs/src/app/[lang]/docs/layout.tsx","apps/design-docs/src/app/[lang]/layout.tsx","apps/design-docs/src/app/[lang]/registry/[name]/page.tsx","apps/design-docs/src/app/[lang]/registry/page.tsx","apps/design-docs/src/app/og/docs/[...slug]/route.tsx","apps/design-docs/src/components/brand-overview-visuals.tsx","apps/design-docs/src/components/color-usage.tsx","apps/design-docs/src/components/component-preview.tsx","apps/design-docs/src/components/gradient-demos.tsx","apps/design-docs/src/components/introduction-hero.tsx","apps/design-docs/src/components/motion-demos.tsx","apps/design-docs/src/components/pattern-demos.tsx","apps/design-docs/src/components/registry/registry-card.tsx","apps/design-docs/src/lib/github.ts","apps/design-docs/src/lib/registry-strings.ts","apps/design-docs/src/lib/registry.ts","apps/idp/src/app/layout.tsx","apps/idp/src/app/oauth/authorize/page.tsx","apps/idp/src/app/page.tsx","apps/idp/src/lib/oidc.ts","apps/landing-page/src/app/[lang]/layout.tsx","apps/landing-page/src/app/api/blog/comments/route.ts","apps/landing-page/src/app/api/blog/reactions/route.ts","apps/landing-page/src/app/api/og/route.ts","apps/landing-page/src/app/apple-icon.tsx","apps/landing-page/src/components/auth/google-one-tap.tsx","apps/landing-page/src/components/cookie-consent-banner.tsx","apps/landing-page/src/components/marketing/ProductHuntSection.tsx","apps/landing-page/src/components/marketing/TestimonialsSection.tsx","apps/landing-page/src/i18n/request.ts","apps/landing-page/src/lib/analytics/emit.ts","apps/landing-page/src/lib/blog-fallback.ts","apps/landing-page/src/lib/constants/playbook-data.ts","apps/landing-page/src/lib/constants/resources-data.ts","apps/landing-page/src/lib/constants/solutions-data.ts","apps/landing-page/src/lib/docs-links.ts","apps/landing-page/src/lib/env.ts","apps/landing-page/src/lib/landing-content.ts","apps/landing-page/src/lib/seo/metadata.ts","apps/landing-page/src/lib/seo/site-routes.ts","apps/landing-page/src/lib/status-checks.ts","apps/landing-page/src/proxy.ts","apps/mail-preview/scripts/export.ts","apps/mail-preview/scripts/render-react-templates.ts","apps/mail-preview/src/app/api/send-test/route.ts","apps/mail-preview/src/app/layout.tsx","apps/mail-preview/src/lib/fixtures.ts","apps/web/next.config.ts","apps/web/src/app/(app)/checkout-return/page.tsx","apps/web/src/app/(app)/choose-plan/page.tsx","apps/web/src/app/(app)/settings/api-keys/page.tsx","apps/web/src/app/(app)/settings/notifications/page.tsx","apps/web/src/app/(app)/settings/provider-keys/page.tsx","apps/web/src/app/(auth)/desktop-auth/complete/page.tsx","apps/web/src/app/(public)/page.tsx","apps/web/src/app/[locale]/welcome/page.tsx","apps/web/src/app/api/account/email-change/route.ts","apps/web/src/app/api/admin/access-invites/route.ts","apps/web/src/app/api/blog/comments/route.ts","apps/web/src/app/api/blog/reactions/route.ts","apps/web/src/app/api/me/public/route.ts","apps/web/src/app/api/organizations/[orgId]/members/route.ts","apps/web/src/app/global-error.tsx","apps/web/src/components/ErrorBoundary.tsx","apps/web/src/components/api-keys/create-api-key-dialog.tsx","apps/web/src/components/appearance/store.ts","apps/web/src/components/auth/auth-banner.tsx","apps/web/src/components/auth/desktop-auth-complete-handoff.tsx","apps/web/src/components/auth/sign-up-form.tsx","apps/web/src/components/billing/billing-self-service.tsx","apps/web/src/components/navigation/public-page-chrome.tsx","apps/web/src/components/notifications/inbox-bell.tsx","apps/web/src/components/notifications/notification-inbox-preview.tsx","apps/web/src/components/notifications/notification-preference-matrix.tsx","apps/web/src/components/notifications/notification-runtime-banner.tsx","apps/web/src/components/settings/security/security-capabilities.ts","apps/web/src/components/settings/security/security-settings-client.tsx","apps/web/src/components/theme-playground/design-md-import.tsx","apps/web/src/components/theme-playground/theme-playground-workbench.tsx","apps/web/src/components/theme-playground/theme-token-data.ts","apps/web/src/lib/api.ts","apps/web/src/lib/api/client.ts","apps/web/src/lib/env.ts","apps/web/src/lib/integrations/catalog.tsx","apps/web/src/lib/permissions.ts","apps/web/src/lib/public-url-defaults.ts","apps/web/src/lib/session-hint.ts","apps/web/src/lib/startup-os/company-context/generate.ts","apps/web/src/lib/startup-os/company-context/projection.ts","apps/web/src/lib/startup-os/conversation.ts","apps/web/src/lib/startup-os/execution.ts","apps/web/src/lib/startup-os/files.ts","apps/web/src/proxy.ts","packages/commerce/billing/src/index.ts","packages/commerce/contracts/src/identity.ts","packages/commerce/legal/src/components/CookieBanner.tsx","packages/commerce/legal/src/documents/config.ts","packages/commerce/legal/src/index.ts","packages/commerce/marketing/src/components/ProductHuntBadge.tsx","packages/commerce/marketing/src/config/index.ts","packages/commerce/marketing/src/index.ts","packages/integrations/email/src/index.ts","packages/integrations/email/src/templates/_layout.ts","packages/integrations/email/src/templates/invitation.tsx"];function ea(e,t){let n=(e??"").replace(Wi,"").split("&&").map(r=>r.trim()).filter(Boolean).join(" && ");return[n.length>0?n:"biome check .",...t].join(" && ")}function ta(e){let t=new RegExp(Uo.allowExpressions.join("|"));return Zi.filter(n=>{try{return t.test(It.readFileSync(pn.join(e,n),"utf8"))}catch{return!1}})}async function Mo(e,t){let n=t.database!=="none",o=[Yi];n&&o.push(qi),o.push(Gi),o.push(Hi);let r={...Uo,allowlist:ta(e)},s={rawInputs:zi,brandLiterals:r,microcopyRules:Qi};n&&(s.repositorySeam=Ji);let i=pn.join(e,"governance.config.json");It.writeFileSync(i,JSON.stringify(s,null,2)+`
|
|
1515
|
+
`);let a=pn.join(e,"package.json"),c;try{c=It.readFileSync(a,"utf8")}catch(p){if(p.code!=="ENOENT")throw p}if(c!==void 0){let p=JSON.parse(c);p.scripts=p.scripts??{};for(let[u,d]of Object.entries(p.scripts))u!=="lint"&&typeof d=="string"&&Xi.test(d)&&delete p.scripts[u];p.scripts.lint=ea(p.scripts.lint,o),It.writeFileSync(a,JSON.stringify(p,null,2)+`
|
|
1516
|
+
`)}return{lints:o,configWritten:!0}}import{createHmac as oa,randomBytes as ra}from"crypto";import Q from"fs";import ae from"path";import{fileURLToPath as sa}from"url";var na=[{id:"v1",key:"nebutra-sailor:scaffold-marker:v1"}];function Do(){let e=na[0];if(!e)throw new Error("license-signing-keys: registry is empty \u2014 at least one key is required.");return e}var ia=sa(import.meta.url),Fo=ae.dirname(ia),jo="scaffold-meta.json",Bo=".nebutra";function aa(e){if(e)return e;let t=[ae.join(Fo,"..","templates"),ae.join(Fo,"..","..","templates")];for(let n of t)if(Q.existsSync(n))return n;return t[0]}function ca(e,t){let n=`${e.cliVersion}|${e.scaffoldedAt}|${e.projectName}|${e.nonce}`;return oa("sha256",t).update(n).digest("hex")}function Vo(e,t){let n=[],o=aa(t.templatesRoot),r=ae.join(e,"LICENSE");if(Q.existsSync(r)){let h=Q.readFileSync(r,"utf-8").slice(0,256);/GNU AFFERO GENERAL PUBLIC LICENSE/i.test(h)&&(Q.renameSync(r,ae.join(e,"LICENSE-AGPL-REFERENCE.md")),n.push("LICENSE-AGPL-REFERENCE.md (preserved upstream AGPL)"))}let s=ae.join(o,"LICENSE-INDEPENDENT.md");if(!Q.existsSync(s))throw new Error(`LICENSE-INDEPENDENT.md template missing at ${s}; cannot emit license.`);Q.copyFileSync(s,ae.join(e,"LICENSE")),n.push("LICENSE");let i=new Date().toISOString(),a=ra(12).toString("hex"),c=Do(),p=ca({cliVersion:t.cliVersion,scaffoldedAt:i,projectName:t.projectName,nonce:a},c.key),u={schemaVersion:1,cliVersion:t.cliVersion,scaffoldedAt:i,projectName:t.projectName,nonce:a,signature:p,signingKeyId:c.id,purpose:"Marks this project as scaffolded by the official `create-sailor` CLI. The Independent Developer License in LICENSE applies as long as this file is present and the signature verifies.",license:{tier:"independent",file:"LICENSE",upgradeUrl:"https://nebutra.com/get-license"}},d=ae.join(e,Bo);Q.mkdirSync(d,{recursive:!0}),Q.writeFileSync(ae.join(d,jo),`${JSON.stringify(u,null,2)}
|
|
1518
1517
|
`),n.push(`${Bo}/${jo}`);let _=ae.join(e,"README.md");if(Q.existsSync(_)){let h=Q.readFileSync(_,"utf-8");h.includes("Nebutra-Sailor Independent Developer License")||(Q.writeFileSync(_,`> **License notice:** scaffolded by \`create-sailor\` under the
|
|
1519
1518
|
> [Nebutra-Sailor Independent Developer License](./LICENSE). Free for
|
|
1520
1519
|
> individuals/OPC with \u2264 1 FTE and < $1M ARR; upgrade for larger teams at
|
|
1521
1520
|
> https://nebutra.com/get-license. The upstream repository remains
|
|
1522
1521
|
> AGPL-3.0 \u2014 see \`LICENSE-AGPL-REFERENCE.md\`.
|
|
1523
1522
|
|
|
1524
|
-
`+h),n.push("README.md (prepended license notice)"))}return{wrote:n}}import
|
|
1525
|
-
`);
|
|
1526
|
-
`);
|
|
1527
|
-
`)}function ce(e,t){
|
|
1528
|
-
`+t):de.writeFileSync(n,t)}function
|
|
1523
|
+
`+h),n.push("README.md (prepended license notice)"))}return{wrote:n}}import Me from"fs";import ln from"path";async function Ko(e,t){let n=ln.join(e,"packages","mcp");if(t==="off"){Me.existsSync(n)&&Me.rmSync(n,{recursive:!0,force:!0});let r=ln.join(e,"packages","cli","src","commands","mcp-server.ts");Me.existsSync(r)&&Me.rmSync(r,{force:!0});return}let o=ln.join(e,".env.example");if(Me.existsSync(o)){let r=Me.readFileSync(o,"utf-8"),s="# MCP Server (Agent-friendly API)";if(!r.includes(s)){let i=["","# =============================================",s,"# Docs: https://modelcontextprotocol.io","# =============================================","# MCP server exposes your SaaS capabilities to AI agents via MCP protocol.","# Run: pnpm mcp-server (starts stdio server)","# No config required for stdio transport. HTTP transport needs:",'MCP_HTTP_PORT="3100"','MCP_API_KEY=""',""].join(`
|
|
1524
|
+
`);Me.appendFileSync(o,i)}}}import lt from"fs";import $o from"path";async function Yo(e,t,n){let o=$o.join(e,"packages","metering"),r;if(t==="auto"?r=n!=="none"?"on":"off":t==="on"||t==="off"?r=t:r="off",r==="off"){lt.existsSync(o)&<.rmSync(o,{recursive:!0,force:!0});return}let s=$o.join(e,".env.example");if(!lt.existsSync(s))return;let i=lt.readFileSync(s,"utf-8"),a="# Metering (usage-based billing)";if(!i.includes(a)){let c=["","# =============================================",a,"# Docs: see packages/commerce/metering/README.md","# =============================================","# ClickHouse-based metering pipeline for consumption billing.",'CLICKHOUSE_URL=""','CLICKHOUSE_USER="default"','CLICKHOUSE_PASSWORD=""','CLICKHOUSE_DATABASE="metering"',""].join(`
|
|
1525
|
+
`);lt.appendFileSync(s,c)}}import de from"fs";import D from"path";var qo=[{id:"sentry",name:"Sentry",region:"both",envVars:["SENTRY_DSN","NEXT_PUBLIC_SENTRY_DSN"],docs:"https://docs.sentry.io",pkg:"@sentry/nextjs",instrumentationFile:"apps/web/instrumentation.ts"},{id:"datadog",name:"Datadog",region:"global",envVars:["DD_API_KEY","DD_APP_KEY","DD_SITE"],docs:"https://docs.datadoghq.com",pkg:"dd-trace",instrumentationFile:"apps/web/instrumentation.ts"},{id:"bugsnag",name:"Bugsnag",region:"global",envVars:["BUGSNAG_API_KEY","NEXT_PUBLIC_BUGSNAG_API_KEY"],docs:"https://docs.bugsnag.com",pkg:"@bugsnag/js",instrumentationFile:"apps/web/src/lib/monitoring/bugsnag.ts"},{id:"aliyun-arms",name:"\u963F\u91CC\u4E91 ARMS",region:"cn",envVars:["ALIYUN_ARMS_LICENSE_KEY","ALIYUN_ARMS_APP_NAME","NEXT_PUBLIC_ARMS_PID"],docs:"https://help.aliyun.com/product/34364.html",instrumentationFile:"apps/web/src/components/monitoring/ArmsScript.tsx"},{id:"tingyun",name:"\u542C\u4E91 TingYun",region:"cn",envVars:["TINGYUN_LICENSE_KEY","NEXT_PUBLIC_TINGYUN_APP_KEY"],docs:"https://www.tingyun.com/docs",instrumentationFile:"apps/web/src/components/monitoring/TingYunScript.tsx"},{id:"none",name:"None",region:"both",envVars:[],docs:""}],ld=qo.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Go(e){return qo.find(t=>t.id===e)}var dn={sentry:{"@sentry/nextjs":"^8.45.0"},datadog:{"dd-trace":"^5.32.0","@datadog/browser-rum":"^5.30.0"},bugsnag:{"@bugsnag/js":"^8.2.0","@bugsnag/plugin-react":"^8.2.0"}};function pa(e){de.mkdirSync(e,{recursive:!0})}function un(e,t){let n=D.join(e,"package.json");if(!de.existsSync(n))return;let o;try{o=JSON.parse(de.readFileSync(n,"utf-8"))}catch(a){console.error(`Failed to parse ${n}:`,a);return}let s={...o.dependencies??{}};for(let[a,c]of Object.entries(t))s[a]||(s[a]=c);let i={...o,dependencies:s};de.writeFileSync(n,JSON.stringify(i,null,2)+`
|
|
1526
|
+
`)}function ce(e,t){pa(D.dirname(e)),de.writeFileSync(e,t)}function dt(e,t){let n=D.join(e,".env.example");de.existsSync(n)?de.appendFileSync(n,`
|
|
1527
|
+
`+t):de.writeFileSync(n,t)}function la(e){let t=`import * as Sentry from "@sentry/nextjs";
|
|
1529
1528
|
|
|
1530
1529
|
Sentry.init({
|
|
1531
1530
|
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
|
@@ -1554,7 +1553,7 @@ Sentry.init({
|
|
|
1554
1553
|
tracesSampleRate: 1.0,
|
|
1555
1554
|
environment: process.env.NODE_ENV,
|
|
1556
1555
|
});
|
|
1557
|
-
`,
|
|
1556
|
+
`,r=`/**
|
|
1558
1557
|
* Next.js instrumentation hook \u2014 wires Sentry into Node and Edge runtimes.
|
|
1559
1558
|
* See https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation
|
|
1560
1559
|
*/
|
|
@@ -1568,14 +1567,14 @@ export async function register() {
|
|
|
1568
1567
|
}
|
|
1569
1568
|
|
|
1570
1569
|
export { captureRequestError as onRequestError } from "@sentry/nextjs";
|
|
1571
|
-
`;ce(D.join(e,"sentry.client.config.ts"),t),ce(D.join(e,"sentry.server.config.ts"),n),ce(D.join(e,"sentry.edge.config.ts"),o),ce(D.join(e,"instrumentation.ts"),
|
|
1570
|
+
`;ce(D.join(e,"sentry.client.config.ts"),t),ce(D.join(e,"sentry.server.config.ts"),n),ce(D.join(e,"sentry.edge.config.ts"),o),ce(D.join(e,"instrumentation.ts"),r)}function da(){return`# Sentry \u2014 error tracking + performance monitoring
|
|
1572
1571
|
# Get your DSN from https://sentry.io/settings/projects/<project>/keys/
|
|
1573
1572
|
SENTRY_DSN=
|
|
1574
1573
|
NEXT_PUBLIC_SENTRY_DSN=
|
|
1575
1574
|
SENTRY_ORG=
|
|
1576
1575
|
SENTRY_PROJECT=
|
|
1577
1576
|
SENTRY_AUTH_TOKEN=
|
|
1578
|
-
`}function
|
|
1577
|
+
`}function ua(e){let t=`/**
|
|
1579
1578
|
* Next.js instrumentation hook \u2014 wires Datadog APM (dd-trace) into Node runtime.
|
|
1580
1579
|
* Edge runtime is not supported by dd-trace; only nodejs is initialized.
|
|
1581
1580
|
*/
|
|
@@ -1623,7 +1622,7 @@ export function initDatadogRum(): void {
|
|
|
1623
1622
|
});
|
|
1624
1623
|
initialized = true;
|
|
1625
1624
|
}
|
|
1626
|
-
`;ce(D.join(e,"instrumentation.ts"),t),ce(D.join(e,"src","lib","monitoring","datadog-rum.ts"),n)}function
|
|
1625
|
+
`;ce(D.join(e,"instrumentation.ts"),t),ce(D.join(e,"src","lib","monitoring","datadog-rum.ts"),n)}function ma(){return`# Datadog \u2014 APM + RUM
|
|
1627
1626
|
# Server APM (dd-trace)
|
|
1628
1627
|
DD_API_KEY=
|
|
1629
1628
|
DD_APP_KEY=
|
|
@@ -1638,7 +1637,7 @@ NEXT_PUBLIC_DD_SITE=datadoghq.com
|
|
|
1638
1637
|
NEXT_PUBLIC_DD_SERVICE=sailor-web
|
|
1639
1638
|
NEXT_PUBLIC_DD_ENV=production
|
|
1640
1639
|
NEXT_PUBLIC_DD_VERSION=
|
|
1641
|
-
`}function
|
|
1640
|
+
`}function ga(e){let t=`/**
|
|
1642
1641
|
* Bugsnag server-side initialization.
|
|
1643
1642
|
* Import this once at the top of your server entrypoint or a shared init module.
|
|
1644
1643
|
*/
|
|
@@ -1687,11 +1686,11 @@ export function getBugsnagErrorBoundary() {
|
|
|
1687
1686
|
errorBoundary = plugin.createErrorBoundary(React) as typeof errorBoundary;
|
|
1688
1687
|
return errorBoundary;
|
|
1689
1688
|
}
|
|
1690
|
-
`;ce(D.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),ce(D.join(e,"src","lib","monitoring","bugsnag.client.tsx"),n)}function
|
|
1689
|
+
`;ce(D.join(e,"src","lib","monitoring","bugsnag.server.ts"),t),ce(D.join(e,"src","lib","monitoring","bugsnag.client.tsx"),n)}function fa(){return`# Bugsnag \u2014 error tracking
|
|
1691
1690
|
BUGSNAG_API_KEY=
|
|
1692
1691
|
NEXT_PUBLIC_BUGSNAG_API_KEY=
|
|
1693
1692
|
APP_VERSION=
|
|
1694
|
-
`}function
|
|
1693
|
+
`}function ya(e){ce(D.join(e,"src","components","monitoring","ArmsScript.tsx"),`"use client";
|
|
1695
1694
|
/**
|
|
1696
1695
|
* \u963F\u91CC\u4E91 ARMS (Application Real-time Monitoring Service) browser agent.
|
|
1697
1696
|
* Injects the official JS agent via next/script.
|
|
@@ -1712,11 +1711,11 @@ export function ArmsScript() {
|
|
|
1712
1711
|
/>
|
|
1713
1712
|
);
|
|
1714
1713
|
}
|
|
1715
|
-
`)}function
|
|
1714
|
+
`)}function Sa(){return`# \u963F\u91CC\u4E91 ARMS \u2014 APM (\u4E2D\u56FD\u533A)
|
|
1716
1715
|
ALIYUN_ARMS_LICENSE_KEY=
|
|
1717
1716
|
ALIYUN_ARMS_APP_NAME=
|
|
1718
1717
|
NEXT_PUBLIC_ARMS_PID=
|
|
1719
|
-
`}function
|
|
1718
|
+
`}function ha(e){ce(D.join(e,"src","components","monitoring","TingYunScript.tsx"),`"use client";
|
|
1720
1719
|
/**
|
|
1721
1720
|
* \u542C\u4E91 Browser Agent (\u524D\u7AEF\u6027\u80FD\u76D1\u63A7).
|
|
1722
1721
|
* Docs: https://www.tingyun.com/docs
|
|
@@ -1734,12 +1733,12 @@ export function TingYunScript() {
|
|
|
1734
1733
|
/>
|
|
1735
1734
|
);
|
|
1736
1735
|
}
|
|
1737
|
-
`)}function
|
|
1736
|
+
`)}function Ea(){return`# \u542C\u4E91 TingYun \u2014 APM (\u4E2D\u56FD\u533A)
|
|
1738
1737
|
TINGYUN_LICENSE_KEY=
|
|
1739
1738
|
NEXT_PUBLIC_TINGYUN_APP_KEY=
|
|
1740
|
-
`}async function Ho(e,t,n="global"){let o=Go(t);if(!o||o.id==="none")return;let
|
|
1741
|
-
`)}}import xt from"fs";import
|
|
1742
|
-
`+t):ue.writeFileSync(n,t)}function
|
|
1739
|
+
`}async function Ho(e,t,n="global"){let o=Go(t);if(!o||o.id==="none")return;let r=D.join(e,"apps","web");if(!de.existsSync(r))return;let s=o.id;try{switch(s){case"sentry":la(r),un(r,dn.sentry),dt(e,da());return;case"datadog":ua(r),un(r,dn.datadog),dt(e,ma());return;case"bugsnag":ga(r),un(r,dn.bugsnag),dt(e,fa());return;case"aliyun-arms":ya(r),dt(e,Sa());return;case"tingyun":ha(r),dt(e,Ea());return;default:return}}catch(i){throw console.error(`Failed to apply monitoring selection "${t}":`,i),new Error(`Monitoring scaffold for "${t}" failed \u2014 see stderr for details.`)}}var Ct=[{id:"novu",name:"Novu",region:"both",envVars:["NOVU_API_KEY","NOVU_APPLICATION_IDENTIFIER"],docs:"https://docs.novu.co",description:"Multi-channel notification infrastructure"},{id:"knock",name:"Knock",region:"global",envVars:["KNOCK_API_KEY","KNOCK_SIGNING_KEY","KNOCK_PUBLIC_API_KEY"],docs:"https://docs.knock.app",description:"Product notifications platform"},{id:"custom",name:"Custom (direct dispatchers)",region:"both",envVars:[],docs:"",description:"Use email + sms + push directly"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function Wo(e){return Ct.find(t=>t.id===e)}var yd=Ct.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Xo(e,t,n="global"){let o=Wo(t);if(!o)throw new Error(`Unknown notifications provider "${t}". Valid ids: ${Ct.map(r=>r.id).join(", ")}`);if(o.id==="none"){z(e,"notifications");return}o.envVars.length>0&&oe(e,{category:"Notifications",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"NOTIFICATIONS_PROVIDER",o.id)}import mn from"fs";import va from"path";async function zo(e,t){let n=va.join(e,"package.json");if(mn.existsSync(n)){let o=mn.readFileSync(n,"utf8"),r=JSON.parse(o);r.name=t,r.version="0.1.0",mn.writeFileSync(n,JSON.stringify(r,null,2)+`
|
|
1740
|
+
`)}}import xt from"fs";import Qe from"path";import{fileURLToPath as ba}from"url";var _a=ba(import.meta.url),Jo=Qe.dirname(_a);function Pa(){let e=[Qe.join(Jo,"..","templates","orm","drizzle"),Qe.join(Jo,"..","..","templates","orm","drizzle")];for(let t of e)if(xt.existsSync(t))return t;return null}function Qo(e,t){xt.mkdirSync(t,{recursive:!0});for(let n of xt.readdirSync(e,{withFileTypes:!0})){let o=Qe.join(e,n.name),r=Qe.join(t,n.name);n.isDirectory()?Qo(o,r):xt.copyFileSync(o,r)}}async function Zo(e,t,n){if(t!=="drizzle")return{applied:!1};if(n!=="postgresql")return{applied:!1,reason:`Drizzle template currently targets Postgres only; --db=${n} keeps Prisma as sole ORM`};let o=Pa();if(!o)return{applied:!1,reason:"Drizzle template directory not found in package \u2014 bundling error"};let r=Qe.join(e,"packages","platform","db-drizzle");return Qo(o,r),{applied:!0}}import ue from"fs";import ut from"path";var wa=["stripe","lemonsqueezy","chinapay","polar"];function er(e){ue.existsSync(e)&&ue.rmSync(e,{recursive:!0,force:!0})}function Aa(e){switch(e){case"stripe":return["stripe"];case"lemon":return["lemonsqueezy"];case"wechat":case"alipay":return["chinapay"]}}function Ia(e,t){let n=ut.join(e,".env.example");ue.existsSync(n)?ue.appendFileSync(n,`
|
|
1741
|
+
`+t):ue.writeFileSync(n,t)}function Ca(e){switch(e){case"stripe":return`# Stripe
|
|
1743
1742
|
STRIPE_SECRET_KEY=
|
|
1744
1743
|
STRIPE_WEBHOOK_SECRET=
|
|
1745
1744
|
`;case"lemon":return`# Lemon Squeezy
|
|
@@ -1754,14 +1753,14 @@ CHINAPAY_WECHAT_ENABLED=true
|
|
|
1754
1753
|
CHINAPAY_APP_ID=
|
|
1755
1754
|
CHINAPAY_APP_SECRET=
|
|
1756
1755
|
CHINAPAY_ALIPAY_ENABLED=true
|
|
1757
|
-
`}}async function
|
|
1758
|
-
`),o=[],
|
|
1759
|
-
`),t)}function
|
|
1760
|
-
`).filter(
|
|
1761
|
-
`);return e.replace(
|
|
1762
|
-
`+
|
|
1763
|
-
`)}}import y from"fs";import g from"path";function
|
|
1764
|
-
`)}let a=g.join(
|
|
1756
|
+
`}}async function tr(e,t){let n=ut.join(e,"packages","commerce","billing");if(!ue.existsSync(n))return;if(t==="none"){er(n);return}let o=ut.join(n,"src"),r=new Set(Aa(t));for(let i of wa)r.has(i)||er(ut.join(o,i));let s=ut.join(o,"checkout","types.ts");if(ue.existsSync(s)){let i=t==="stripe"?"stripe":t==="lemon"?"lemonsqueezy":"chinapay",a=ue.readFileSync(s,"utf8"),c=a.replace(/export type CheckoutProviderType\s*=\s*[^;]+;/,`export type CheckoutProviderType = "${i}";`);c!==a&&ue.writeFileSync(s,c)}Ia(e,Ca(t))}import _e from"fs";import Ze from"path";var rr=new Set(["siliconflow","volcengine-ark","bailian","moonshot"]),gn=/@sailor:([^\s*]+)/;function xa(e,t){let{providerIds:n,customEndpoint:o}=t;if(e.startsWith("provider:")){let r=e.slice(9);return{marker:e,keep:n.includes(r)}}if(e==="cn-compatible"){let r=n.some(s=>rr.has(s));return{marker:e,keep:r||!!o}}if(e.startsWith("cn-instance:")){let r=e.slice(12);return{marker:e,keep:n.includes(r)}}return e==="custom-endpoint"?{marker:e,keep:!!o}:e==="registry-entries"?{marker:e,keep:!0}:{marker:e,keep:!0}}function nr(e){return e.replace(/\s*\/\/\s*@sailor:[^\n]*$/,"")}function or(e){return e.replace(/\s*#\s*@sailor:[^\n]*$/,"")}function sr(e,t){let n=e.split(`
|
|
1757
|
+
`),o=[],r=e.includes("#"),s=0;for(;s<n.length;){let i=n[s],a=i.match(gn);if(!a){o.push(i),s++;continue}let{marker:c,keep:p}=xa(a[1],t);if(c==="registry-entries"){o.push(r?or(i):nr(i)),s++;continue}if(p){let u=r?or(i):nr(i);u.trim().length>0&&o.push(u);let d=s+1;for(;d<n.length&&n[d].trim()!==""&&!gn.test(n[d]);)o.push(n[d]),d++;d<n.length&&n[d].trim()===""&&(o.push(n[d]),d++),s=d}else{let u=s+1;for(;u<n.length&&n[u].trim()!==""&&!gn.test(n[u]);)u++;u<n.length&&n[u].trim()===""&&u++,s=u}}return Ra(o.join(`
|
|
1758
|
+
`),t)}function Ra(e,t){let{providerIds:n,customEndpoint:o}=t,r=new Set;for(let p of n)["openai","anthropic","google","mistral","xai"].includes(p)&&r.add(p),r.add(p.replace(/-/g,"_")),r.add(p);o&&r.add("custom");let s=/createProviderRegistry\(\{([\s\S]*?)\}\)/,i=e.match(s);if(!i)return e;let c=i[1].split(`
|
|
1759
|
+
`).filter(p=>{let u=p.trim();if(u===""||u.startsWith("//"))return!0;let d=u.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*,?$/);return d?r.has(d[1]):!0}).join(`
|
|
1760
|
+
`);return e.replace(s,`createProviderRegistry({${c}})`)}function ka(e,t){let n=Ze.join(t,"registry.ts.template"),o=_e.readFileSync(n,"utf-8");return sr(o,e)}function Ta(e,t){let n=Ze.join(t,".env.example.template"),o=_e.readFileSync(n,"utf-8");return sr(o,e)}async function ir(e,t,n){let o=ka(t,n),r=Ta(t,n),s=Ze.join(e,"packages/ai/agents/src");await _e.promises.mkdir(s,{recursive:!0}),await _e.promises.writeFile(Ze.join(s,"registry.ts"),o),await _e.promises.appendFile(Ze.join(e,".env.example"),`
|
|
1761
|
+
`+r);let i={ai:"latest"},{providerIds:a,customEndpoint:c}=t;(a.includes("openai")||c||a.some(u=>rr.has(u)))&&(i["@ai-sdk/openai"]="latest",i["@ai-sdk/openai-compatible"]="latest"),a.includes("anthropic")&&(i["@ai-sdk/anthropic"]="latest"),a.includes("google")&&(i["@ai-sdk/google"]="latest"),a.includes("mistral")&&(i["@ai-sdk/mistral"]="latest"),a.includes("xai")&&(i["@ai-sdk/openai"]="latest");let p=Ze.join(e,"package.json");if(_e.existsSync(p)){let u=JSON.parse(await _e.promises.readFile(p,"utf-8"));u.dependencies||(u.dependencies={});for(let[d,_]of Object.entries(i))u.dependencies[d]=_;await _e.promises.writeFile(p,JSON.stringify(u,null,2)+`
|
|
1762
|
+
`)}}import y from"fs";import g from"path";function ar(e,t){if(!y.existsSync(e))return;let n=y.readdirSync(e);for(let o of n){let r=g.join(e,o);y.statSync(r).isDirectory()?ar(r,t):t(r)}}async function cr(e,t){let n=g.join(e,"package.json");if(!y.existsSync(n))return;let o=JSON.parse(y.readFileSync(n,"utf8"));if(t.orm!=="prisma"){let r=g.join(e,"packages","db");if(y.existsSync(r)){let s=g.join(r,"prisma");y.existsSync(s)&&y.rmSync(s,{recursive:!0,force:!0});let i=g.join(r,"package.json");if(y.existsSync(i)){let c=JSON.parse(y.readFileSync(i,"utf8"));c.dependencies&&delete c.dependencies["@prisma/client"],c.devDependencies&&delete c.devDependencies.prisma,y.writeFileSync(i,JSON.stringify(c,null,2)+`
|
|
1763
|
+
`)}let a=g.join(r,"src","index.ts");y.existsSync(a)&&y.writeFileSync(a,`
|
|
1765
1764
|
export const prisma = {} as any;
|
|
1766
1765
|
export const db = {} as any;
|
|
1767
1766
|
export type PrismaClient = any;
|
|
@@ -1807,7 +1806,7 @@ export type UsageAggregate = any;
|
|
|
1807
1806
|
export type UsageLedgerEntry = any;
|
|
1808
1807
|
export type UsageType = any;
|
|
1809
1808
|
export type UsageLedgerSource = any;
|
|
1810
|
-
`)}o.scripts?.postinstall&&(o.scripts.postinstall=o.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let
|
|
1809
|
+
`)}o.scripts?.postinstall&&(o.scripts.postinstall=o.scripts.postinstall.replace(/prisma generate/g,'echo "ORM Disabled"'))}if(!t.i18n){let r=g.join(e,"apps");if(y.existsSync(r)){let s=y.readdirSync(r);for(let i of s){let a=g.join(r,i);if(!y.statSync(a).isDirectory())continue;let c=g.join(a,"src","app");if(!y.existsSync(c))continue;["[lang]","[locale]"].forEach(S=>{let m=g.join(c,S);if(y.existsSync(m)){let P=y.readdirSync(m);for(let G of P)y.renameSync(g.join(m,G),g.join(c,G));y.rmdirSync(m)}}),["src/middleware.ts","middleware.ts"].forEach(S=>{let m=g.join(a,S);y.existsSync(m)&&y.rmSync(m)});let p=g.join(a,"src","lib");y.existsSync(p)||y.mkdirSync(p,{recursive:!0});let u=g.join(p,"mock-i18n.ts");y.writeFileSync(u,`
|
|
1811
1810
|
import React from 'react';
|
|
1812
1811
|
export function useTranslations(namespace?: string): any { return (key: string) => key; }
|
|
1813
1812
|
export function useLocale() { return 'en'; }
|
|
@@ -1825,7 +1824,7 @@ export const useRouter = () => ({ push: (...args: any[]) => {}, replace: (...arg
|
|
|
1825
1824
|
export default function createMiddleware(...args: any[]) { return (req: any) => req; }
|
|
1826
1825
|
export function createNavigation(...args: any[]) { return { Link, redirect, usePathname, useRouter, getPathname: () => '/' }; }
|
|
1827
1826
|
export function defineRouting<T>(config: T): T { return config; }
|
|
1828
|
-
`);let _=g.join(
|
|
1827
|
+
`);let _=g.join(p,"mock-i18n.d.ts");y.writeFileSync(_,`declare module '@/lib/mock-i18n' {
|
|
1829
1828
|
export function useTranslations(namespace?: string): any;
|
|
1830
1829
|
export function useLocale(): string;
|
|
1831
1830
|
export const NextIntlClientProvider: React.FC<any>;
|
|
@@ -1843,19 +1842,19 @@ export function defineRouting<T>(config: T): T { return config; }
|
|
|
1843
1842
|
export function createNavigation(...args: any[]): any;
|
|
1844
1843
|
export function defineRouting<T>(config: T): T;
|
|
1845
1844
|
}
|
|
1846
|
-
`),y.writeFileSync(g.join(
|
|
1845
|
+
`),y.writeFileSync(g.join(p,"mock-i18n-index.ts"),`
|
|
1847
1846
|
export * from './mock-i18n';
|
|
1848
1847
|
export { default } from './mock-i18n';
|
|
1849
1848
|
`);let h=g.join(a,"tsconfig.json");if(y.existsSync(h))try{let S=y.readFileSync(h,"utf8");if(S.includes('"paths": {')){let m=S.replace(/"paths":\s*\{/,`"paths": {
|
|
1850
1849
|
"next-intl": ["./src/lib/mock-i18n"],
|
|
1851
|
-
"next-intl/*": ["./src/lib/mock-i18n"],`);y.writeFileSync(h,m)}}catch{}let f=g.join(a,"src");y.existsSync(f)&&
|
|
1850
|
+
"next-intl/*": ["./src/lib/mock-i18n"],`);y.writeFileSync(h,m)}}catch{}let f=g.join(a,"src");y.existsSync(f)&&ar(f,S=>{if(!S.endsWith(".ts")&&!S.endsWith(".tsx"))return;let m=y.readFileSync(S,"utf8"),P=!1;S.endsWith("src/app/layout.tsx")&&m.includes("../providers")&&(m=m.replace(/from\s+['"]\.\.\/providers['"]/g,"from './providers'"),P=!0),m=m.replace(/params:\s*Promise<\{[^}]*(lang|locale)[^}]*\}>/g,"params: any"),m=m.replace(/\(\{\s*params\s*\}\s*:\s*\{\s*params:\s*any\s*\}\)/g,"({ params }: any)"),m.match(/locale\s*:\s*any/)&&(m=m.replace(/locale\s*:\s*any/g,"locale: string"),P=!0),m.match(/lang\s*:\s*any/)&&(m=m.replace(/lang\s*:\s*any/g,"lang: string"),P=!0),m.match(/requestLocale\s*:\s*any/)&&(m=m.replace(/requestLocale\s*:\s*any/g,"requestLocale: string"),P=!0),m.match(/\(locale\s*=\s*(.*)\)/)&&(m=m.replace(/\(locale\s*=\s*(.*)\)/g,"() "),P=!0),m.match(/export\s+default\s+async\s+function\s+LangLayout/)&&(m=m.replace(/export\s+default\s+async\s+function\s+LangLayout\s*\(\s*\{\s*children\s*,\s*params\s*\}\s*:\s*LangLayoutProps\s*\)/g,"export default async function LangLayout({ children }: { children: React.ReactNode })"),P=!0),(S.endsWith("src/app/layout.tsx")||S.endsWith("src/app/sitemap.ts")||S.endsWith("src/app/robots.ts")||S.endsWith("src/components/ui/locale-switcher.tsx")||S.endsWith("src/app/(marketing)/blog/[slug]/page.tsx"))&&(m=m.replace(/const\s+\{\s*lang\s*\}\s*=\s*(await\s+)?params;?/g,'const lang = "en";'),m=m.replace(/const\s+\{\s*locale\s*\}\s*=\s*(await\s+)?params;?/g,'const locale = "en";'),m=m.replace(/const\s+locale\s*=\s*lang\s+as\s+Locale;?/g,'const locale = "en";'),m=m.replace(/\(l\)\s*=>/g,"(l: any) =>"),P=!0),S.endsWith("src/i18n/request.ts")&&(m=m.replace(/async\s*\(\{\s*requestLocale\s*\}\)/g,"async ({ requestLocale }: any)"),P=!0),(m.match(/locale\s*:/)||m.match(/lang\s*:/))&&(P=!0),P&&y.writeFileSync(S,m)});let E=g.join(a,"package.json");if(y.existsSync(E)){let S=JSON.parse(y.readFileSync(E,"utf8"));S.dependencies&&delete S.dependencies["next-intl"],y.writeFileSync(E,JSON.stringify(S,null,2)+`
|
|
1852
1851
|
`)}}}}y.writeFileSync(n,JSON.stringify(o,null,2)+`
|
|
1853
|
-
`)}function b(e){try{y.rmSync(e,{recursive:!0,force:!0})}catch{}}function
|
|
1854
|
-
`)}function
|
|
1855
|
-
`);
|
|
1856
|
-
`)}async function
|
|
1857
|
-
`);
|
|
1858
|
-
`)}async function
|
|
1852
|
+
`)}function b(e){try{y.rmSync(e,{recursive:!0,force:!0})}catch{}}function Na(e,t){if(!y.existsSync(e))return;let n;try{n=JSON.parse(y.readFileSync(e,"utf8"))}catch{return}let o=!1;if(n.dependencies&&t in n.dependencies){let{[t]:r,...s}=n.dependencies;n={...n,dependencies:s},o=!0}if(n.devDependencies&&t in n.devDependencies){let{[t]:r,...s}=n.devDependencies;n={...n,devDependencies:s},o=!0}o&&y.writeFileSync(e,JSON.stringify(n,null,2)+`
|
|
1853
|
+
`)}function pr(e,t){t.cronJobs||(b(g.join(e,"apps/web/src/app/api/cron")),b(g.join(e,"packages/integrations/queue/src/scheduled"))),t.auditLog||(b(g.join(e,"apps/web/src/app/[locale]/(app)/settings/audit-log")),b(g.join(e,"apps/web/src/app/api/audit-logs")),b(g.join(e,"apps/web/src/components/audit"))),t.apiKeys||(b(g.join(e,"apps/web/src/app/[locale]/(app)/settings/api-keys")),b(g.join(e,"apps/web/src/app/api/api-keys")),b(g.join(e,"apps/web/src/components/api-keys"))),t.webhooks||(b(g.join(e,"apps/web/src/app/[locale]/(app)/settings/webhooks")),b(g.join(e,"apps/web/src/app/api/webhooks")),b(g.join(e,"apps/web/src/components/webhooks")),b(g.join(e,"packages/integrations/webhooks"))),t.commandPalette||(b(g.join(e,"apps/web/src/components/command-palette")),b(g.join(e,"apps/web/src/app/[locale]/providers/command-palette-mount.tsx"))),t.cookieConsent||(b(g.join(e,"apps/landing-page/src/components/cookie-consent-banner.tsx")),b(g.join(e,"apps/landing-page/src/components/__tests__/cookie-consent-banner.test.tsx")),b(g.join(e,"apps/landing-page/src/lib/cookie-consent.ts")),b(g.join(e,"apps/landing-page/src/lib/__tests__/cookie-consent.test.ts")),b(g.join(e,"apps/web/src/app/api/cookie-consent"))),t.legalPages||(b(g.join(e,"apps/landing-page/src/app/[lang]/(legal)/legal")),b(g.join(e,"apps/landing-page/src/lib/legal-documents.ts")),b(g.join(e,"apps/landing-page/src/lib/__tests__/legal-documents.test.ts"))),t.chinaCompliance||(b(g.join(e,"packages/ops/china-compliance")),b(g.join(e,"apps/landing-page/src/components/icp-footer.tsx")),b(g.join(e,"apps/landing-page/src/components/__tests__/icp-footer.test.tsx")),b(g.join(e,"apps/web/src/components/auth/wechat-login-button.tsx")),b(g.join(e,"apps/web/src/components/auth/__tests__/wechat-login-button.test.tsx")),Na(g.join(e,"apps/web/package.json"),"@nebutra/china-compliance"))}import et from"fs";import lr from"path";var dr=/^--\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/m;function Oa(e){let t=dr.exec(e);if(!t)return null;let[,n,o]=t,r=o.split("|").map(s=>s.trim()).filter(Boolean);return{flag:n,values:r}}function La(e){return e.replace(dr,"").replace(/^\n/,"")}function fn(e,t){let n={kept:[],removed:[],skipped:[]};if(!et.existsSync(e))return n;let o=et.readdirSync(e,{withFileTypes:!0}).filter(r=>r.isDirectory()).sort((r,s)=>r.name.localeCompare(s.name));for(let r of o){let s=lr.join(e,r.name),i=lr.join(s,"migration.sql");if(!et.existsSync(i)){n.skipped.push(r.name);continue}let a=et.readFileSync(i,"utf8"),c=Oa(a);if(!c){n.skipped.push(r.name);continue}let p=t[c.flag];if(p!==void 0&&c.values.includes(p)){et.writeFileSync(i,La(a)),n.kept.push(r.name);continue}et.rmSync(s,{recursive:!0,force:!0}),n.removed.push(r.name)}return n}import{getSchema as Ua,printSchema as Ma}from"@mrleebo/prisma-ast";var Da=/^\/\/\/\s*@conditional\(([A-Za-z][A-Za-z0-9_-]*)=([^)]+)\)\s*$/;function Fa(e){return e.type==="comment"&&e.text.trim().startsWith("//")}function ja(e){let t=Da.exec(e.trim());if(!t)return null;let[,n,o]=t,r=o.split("|").map(s=>s.trim()).filter(s=>s.length>0);return{flag:n,values:r}}function Ba(e,t){for(let n=t-1;n>=0;n--){let o=e[n];if(o.type==="comment"){let r=ja(o.text);if(r)return{annIndex:n,parsed:r};continue}break}return null}function Va(e){return e.type==="model"||e.type==="enum"}function yn(e,t){let n=Ua(e),o=new Set;for(let a=0;a<n.list.length;a++){let c=n.list[a];if(!Va(c))continue;let p=Ba(n.list,a);if(!p)continue;let u=t[p.parsed.flag];if(u!==void 0&&p.parsed.values.includes(u))o.add(p.annIndex);else{o.add(a);for(let h=a-1;h>=0;h--){let f=n.list[h];if(Fa(f)){o.add(h);continue}break}let _=n.list[a+1];_&&_.type==="break"&&o.add(a+1)}}let r=n.list.filter((a,c)=>!o.has(c)),s=[];for(let a of r){let c=s[s.length-1];a.type==="break"&&c&&c.type==="break"||s.push(a)}return Ma({type:"schema",list:s})}import tt from"fs";import mr from"path";var Rt=[{id:"qstash",name:"Upstash QStash",region:"both",envVars:["QSTASH_TOKEN","QSTASH_CURRENT_SIGNING_KEY","QSTASH_NEXT_SIGNING_KEY"],docs:"https://upstash.com/docs/qstash",description:"Serverless HTTP-based queue"},{id:"bullmq",name:"BullMQ",region:"both",envVars:["REDIS_URL"],docs:"https://docs.bullmq.io",description:"Redis-backed job queue"},{id:"sqs",name:"AWS SQS",region:"global",envVars:["AWS_SQS_QUEUE_URL","AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_REGION"],docs:"https://docs.aws.amazon.com/AWSSimpleQueueService/",description:"AWS managed queue"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip queue package"}];function ur(e){return Rt.find(t=>t.id===e)}var Kd=Rt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function gr(e){return tt.existsSync(e)?tt.readFileSync(e,"utf-8"):null}function Ka(e,t){let n=mr.join(e,".env.example"),o=gr(n);if(o===null)return;let r=`# Queue: ${t.name}`;if(o.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
|
|
1854
|
+
`);tt.appendFileSync(n,s)}function $a(e,t,n){let o=mr.join(e,".env.example"),r=gr(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?tt.writeFileSync(o,r.replace(s,`${t}="${n}"`)):tt.appendFileSync(o,`${t}="${n}"
|
|
1855
|
+
`)}async function fr(e,t,n){let o=Re(e,"queue");if(t==="none"){o&&tt.rmSync(o,{recursive:!0,force:!0});return}let r=ur(t);if(!r)throw new Error(`Unknown queue provider "${t}". Valid ids: ${Rt.map(s=>s.id).join(", ")}`);o&&(Ka(e,r),$a(e,"QUEUE_PROVIDER",t))}import me from"fs";import Pe from"path";import{fileURLToPath as Ya}from"url";var qa=Ya(import.meta.url),yr=Pe.dirname(qa),Ga=/\.(md|mdx|json|ts|tsx|js|mjs|cjs|yaml|yml|css|html|toml|py)$/,Ha=["backends/gateway","infra","e2e","tests"];function Wa(){let e=[Pe.join(yr,"..","templates"),Pe.join(yr,"..","..","templates")];for(let t of e)if(me.existsSync(t))return t;return e[0]}async function Sr(e,t){let n=Wa(),o=[],r=[],s=[...Ha,...t.withWorkflows?["workflows"]:[],...t.withPythonBackend?["backends/python"]:[]];for(let i of s){let a=Pe.join(n,i);if(!me.existsSync(a)){r.push(i);continue}let c=Pe.join(e,i);hr(a,c),Er(c,{"{PRODUCT_NAME}":t.projectName}),o.push(i)}return{applied:o,skipped:r}}function hr(e,t){me.mkdirSync(t,{recursive:!0});for(let n of me.readdirSync(e,{withFileTypes:!0})){let o=Pe.join(e,n.name),r=Pe.join(t,n.name);n.isDirectory()?hr(o,r):me.existsSync(r)||me.copyFileSync(o,r)}}function Er(e,t){for(let n of me.readdirSync(e,{withFileTypes:!0})){let o=Pe.join(e,n.name);if(n.isDirectory()){Er(o,t);continue}if(!Ga.test(n.name))continue;let r=me.readFileSync(o,"utf-8"),s=!1;for(let[i,a]of Object.entries(t))r.includes(i)&&(r=r.split(i).join(a),s=!0);s&&me.writeFileSync(o,r)}}import nt from"fs";import br from"path";var kt=[{id:"meilisearch",name:"Meilisearch",region:"both",envVars:["MEILISEARCH_HOST","MEILISEARCH_MASTER_KEY"],docs:"https://docs.meilisearch.com",description:"Self-hostable search"},{id:"typesense",name:"Typesense",region:"both",envVars:["TYPESENSE_HOST","TYPESENSE_PORT","TYPESENSE_PROTOCOL","TYPESENSE_API_KEY"],docs:"https://typesense.org/docs",description:"Open-source search"},{id:"algolia",name:"Algolia",region:"global",envVars:["ALGOLIA_APP_ID","ALGOLIA_ADMIN_API_KEY","ALGOLIA_SEARCH_API_KEY"],docs:"https://www.algolia.com/doc/",description:"Managed search as a service"},{id:"pgvector",name:"pgvector (Postgres)",region:"both",envVars:["DATABASE_URL"],docs:"https://github.com/pgvector/pgvector",description:"Postgres vector + full-text"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:"Skip search package"}];function vr(e){return kt.find(t=>t.id===e)}var Zd=kt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function _r(e){return nt.existsSync(e)?nt.readFileSync(e,"utf-8"):null}function Xa(e,t){let n=br.join(e,".env.example"),o=_r(n);if(o===null)return;let r=`# Search: ${t.name}`;if(o.includes(r))return;let s=["","# =============================================",r,`# Docs: ${t.docs}`,"# =============================================",...t.envVars.map(i=>`${i}=""`),""].join(`
|
|
1856
|
+
`);nt.appendFileSync(n,s)}function za(e,t,n){let o=br.join(e,".env.example"),r=_r(o);if(r===null)return;let s=new RegExp(`^${t}=.*$`,"m");s.test(r)?nt.writeFileSync(o,r.replace(s,`${t}="${n}"`)):nt.appendFileSync(o,`${t}="${n}"
|
|
1857
|
+
`)}async function Pr(e,t,n){let o=Re(e,"search");if(t==="none"){o&&nt.rmSync(o,{recursive:!0,force:!0});return}let r=vr(t);if(!r)throw new Error(`Unknown search provider "${t}". Valid ids: ${kt.map(s=>s.id).join(", ")}`);o&&(Xa(e,r),za(e,"SEARCH_PROVIDER",t))}import we from"fs";import De from"path";function Ja(e){let t=[De.join(e,"packages","db"),De.join(e,"apps","web")];for(let n of t){let o=De.join(n,"prisma","schema.prisma");if(we.existsSync(o))return{packageDir:n,seedPath:De.join(n,"prisma","seed.ts"),packageJsonPath:De.join(n,"package.json")}}return null}function Qa(e){try{let t=we.readFileSync(e,"utf8"),n=new Set,o=/^\s*model\s+(\w+)\s*\{/gm,r=o.exec(t);for(;r;)n.add(r[1]),r=o.exec(t);return n}catch{return new Set}}function Za(e,t){return!t||e==="none"?` // Skipping admin user \u2014 auth=${JSON.stringify(e)} (or no User model).`:e==="clerk"?` try {
|
|
1859
1858
|
const admin = await prisma.user.create({
|
|
1860
1859
|
data: {
|
|
1861
1860
|
clerkId: "user_mock_admin",
|
|
@@ -1886,7 +1885,7 @@ export { default } from './mock-i18n';
|
|
|
1886
1885
|
console.log("\\u2713 Created admin user:", admin.email);
|
|
1887
1886
|
} catch (err) {
|
|
1888
1887
|
console.warn("\\u26A0 Admin user creation skipped:", (err as Error).message);
|
|
1889
|
-
}`}function
|
|
1888
|
+
}`}function ec(e,t){let n=t.has("Tenant"),o=t.has("User"),r=t.has("Project"),s=Za(e,o),i=n?` let tenants: Array<{ id: string; name: string }> = [];
|
|
1890
1889
|
try {
|
|
1891
1890
|
tenants = await Promise.all([
|
|
1892
1891
|
prisma.tenant.create({
|
|
@@ -1903,7 +1902,7 @@ export { default } from './mock-i18n';
|
|
|
1903
1902
|
} catch (err) {
|
|
1904
1903
|
console.warn("\\u26A0 Tenant creation skipped:", (err as Error).message);
|
|
1905
1904
|
}`:` const tenants: Array<{ id: string; name: string }> = [];
|
|
1906
|
-
console.log("\\u2139 No Tenant model in schema \u2014 skipping tenant seed.");`,a=
|
|
1905
|
+
console.log("\\u2139 No Tenant model in schema \u2014 skipping tenant seed.");`,a=r&&n?` for (const tenant of tenants) {
|
|
1907
1906
|
try {
|
|
1908
1907
|
await prisma.project.createMany({
|
|
1909
1908
|
data: [
|
|
@@ -1939,7 +1938,7 @@ async function main(): Promise<void> {
|
|
|
1939
1938
|
${i}
|
|
1940
1939
|
|
|
1941
1940
|
// --- Admin user ------------------------------------------------------
|
|
1942
|
-
${
|
|
1941
|
+
${s}
|
|
1943
1942
|
|
|
1944
1943
|
// --- Sample projects per tenant --------------------------------------
|
|
1945
1944
|
${a}
|
|
@@ -1955,12 +1954,12 @@ main()
|
|
|
1955
1954
|
.finally(async () => {
|
|
1956
1955
|
await prisma.$disconnect();
|
|
1957
1956
|
});
|
|
1958
|
-
`}function
|
|
1959
|
-
`)}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`[create-sailor] Failed to patch seed scripts in ${e}: ${n}`)}}async function
|
|
1960
|
-
`+t):
|
|
1957
|
+
`}function tc(e){if(we.existsSync(e))try{let t=we.readFileSync(e,"utf8"),n=JSON.parse(t),o=n.scripts??{},r=!1;o["db:seed"]||(o["db:seed"]="prisma db seed",r=!0);let s=n.prisma??{};if(s.seed||(s.seed="tsx prisma/seed.ts",r=!0),!r)return;let i={...n,scripts:o,prisma:s};we.writeFileSync(e,JSON.stringify(i,null,2)+`
|
|
1958
|
+
`)}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`[create-sailor] Failed to patch seed scripts in ${e}: ${n}`)}}async function wr(e,t){let n=Ja(e);if(n)try{let o=De.join(n.packageDir,"prisma","schema.prisma"),r=Qa(o),s=ec(t,r),i=De.dirname(n.seedPath);we.existsSync(i)||we.mkdirSync(i,{recursive:!0}),we.writeFileSync(n.seedPath,s),tc(n.packageJsonPath)}catch(o){let r=o instanceof Error?o.message:String(o);throw console.error(`[create-sailor] Failed to generate seed data: ${r}`),new Error(`Unable to write prisma/seed.ts: ${r}`)}}import Ae from"fs";import Fe from"path";var Tt=[{id:"twilio",name:"Twilio",region:"global",envVars:["TWILIO_ACCOUNT_SID","TWILIO_AUTH_TOKEN","TWILIO_FROM_NUMBER"],docs:"https://www.twilio.com/docs/sms",pkgs:["twilio"]},{id:"messagebird",name:"MessageBird (Bird)",region:"global",envVars:["MESSAGEBIRD_ACCESS_KEY","MESSAGEBIRD_ORIGINATOR"],docs:"https://developers.messagebird.com/api/sms-messaging/",pkgs:["messagebird"]},{id:"plivo",name:"Plivo",region:"global",envVars:["PLIVO_AUTH_ID","PLIVO_AUTH_TOKEN","PLIVO_FROM_NUMBER"],docs:"https://www.plivo.com/docs/sms/",pkgs:["plivo"]},{id:"aliyun-sms",name:"\u963F\u91CC\u4E91\u77ED\u4FE1 Aliyun SMS",region:"cn",envVars:["ALIYUN_SMS_ACCESS_KEY","ALIYUN_SMS_ACCESS_SECRET","ALIYUN_SMS_SIGN_NAME","ALIYUN_SMS_TEMPLATE_CODE","ALIYUN_SMS_ENDPOINT"],docs:"https://help.aliyun.com/product/44282.html",pkgs:["@alicloud/dysmsapi20170525","@alicloud/openapi-client"]},{id:"tencent-sms",name:"\u817E\u8BAF\u4E91\u77ED\u4FE1 Tencent SMS",region:"cn",envVars:["TENCENT_SMS_SECRET_ID","TENCENT_SMS_SECRET_KEY","TENCENT_SMS_SDK_APP_ID","TENCENT_SMS_SIGN_NAME","TENCENT_SMS_TEMPLATE_ID","TENCENT_SMS_REGION"],docs:"https://cloud.tencent.com/document/product/382",pkgs:["tencentcloud-sdk-nodejs-sms"]},{id:"yunpian",name:"\u4E91\u7247 Yunpian",region:"cn",envVars:["YUNPIAN_API_KEY","YUNPIAN_SIGN"],docs:"https://www.yunpian.com/official/document/sms/zh_CN/introduction_product_intro",pkgs:["yunpian-nodejs-sdk"]},{id:"none",name:"None",region:"both",envVars:[],docs:""}],pu=Tt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});function Ar(e){return Tt.find(t=>t.id===e)}var nc="@nebutra/sms",oc={twilio:"^5.3.6",messagebird:"^4.0.1",plivo:"^4.73.0","@alicloud/dysmsapi20170525":"^2.0.24","@alicloud/openapi-client":"^0.4.12","tencentcloud-sdk-nodejs-sms":"^4.0.970","yunpian-nodejs-sdk":"^0.0.2"};function Sn(e,t){Ae.mkdirSync(Fe.dirname(e),{recursive:!0}),Ae.writeFileSync(e,t)}function rc(e,t){let n=Fe.join(e,".env.example");Ae.existsSync(n)?Ae.appendFileSync(n,`
|
|
1959
|
+
`+t):Ae.writeFileSync(n,t)}function sc(e){if(e.envVars.length===0)return"";let t=`# SMS provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
|
|
1961
1960
|
`);return`${t}
|
|
1962
1961
|
${n}
|
|
1963
|
-
`}var
|
|
1962
|
+
`}var ic=`/**
|
|
1964
1963
|
* Inputs for the \`sendSms\` wrapper. Keep this surface portable across
|
|
1965
1964
|
* providers \u2014 provider-specific options belong in the wrapper itself.
|
|
1966
1965
|
*/
|
|
@@ -1980,7 +1979,7 @@ export interface SendSmsResult {
|
|
|
1980
1979
|
provider: string;
|
|
1981
1980
|
raw?: unknown;
|
|
1982
1981
|
}
|
|
1983
|
-
`;function
|
|
1982
|
+
`;function ac(){return`import twilio from "twilio";
|
|
1984
1983
|
import type { SendSmsInput, SendSmsResult } from "./types";
|
|
1985
1984
|
|
|
1986
1985
|
let client: ReturnType<typeof twilio> | null = null;
|
|
@@ -2015,7 +2014,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
|
|
|
2015
2014
|
}
|
|
2016
2015
|
|
|
2017
2016
|
export type { SendSmsInput, SendSmsResult } from "./types";
|
|
2018
|
-
`}function
|
|
2017
|
+
`}function cc(){return`import messagebird from "messagebird";
|
|
2019
2018
|
import type { SendSmsInput, SendSmsResult } from "./types";
|
|
2020
2019
|
|
|
2021
2020
|
let client: ReturnType<typeof messagebird> | null = null;
|
|
@@ -2053,7 +2052,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
|
|
|
2053
2052
|
}
|
|
2054
2053
|
|
|
2055
2054
|
export type { SendSmsInput, SendSmsResult } from "./types";
|
|
2056
|
-
`}function
|
|
2055
|
+
`}function pc(){return`import plivo from "plivo";
|
|
2057
2056
|
import type { SendSmsInput, SendSmsResult } from "./types";
|
|
2058
2057
|
|
|
2059
2058
|
let client: InstanceType<typeof plivo.Client> | null = null;
|
|
@@ -2092,7 +2091,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
|
|
|
2092
2091
|
}
|
|
2093
2092
|
|
|
2094
2093
|
export type { SendSmsInput, SendSmsResult } from "./types";
|
|
2095
|
-
`}function
|
|
2094
|
+
`}function lc(){return`import Dysmsapi, { SendSmsRequest } from "@alicloud/dysmsapi20170525";
|
|
2096
2095
|
import * as $OpenApi from "@alicloud/openapi-client";
|
|
2097
2096
|
import type { SendSmsInput, SendSmsResult } from "./types";
|
|
2098
2097
|
|
|
@@ -2141,7 +2140,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
|
|
|
2141
2140
|
}
|
|
2142
2141
|
|
|
2143
2142
|
export type { SendSmsInput, SendSmsResult } from "./types";
|
|
2144
|
-
`}function
|
|
2143
|
+
`}function dc(){return`import * as tencentcloud from "tencentcloud-sdk-nodejs-sms";
|
|
2145
2144
|
import type { SendSmsInput, SendSmsResult } from "./types";
|
|
2146
2145
|
|
|
2147
2146
|
const SmsClient = tencentcloud.sms.v20210111.Client;
|
|
@@ -2206,7 +2205,7 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
|
|
|
2206
2205
|
}
|
|
2207
2206
|
|
|
2208
2207
|
export type { SendSmsInput, SendSmsResult } from "./types";
|
|
2209
|
-
`}function
|
|
2208
|
+
`}function uc(){return`// @ts-expect-error \u2014 yunpian-nodejs-sdk ships no type declarations
|
|
2210
2209
|
import Yunpian from "yunpian-nodejs-sdk";
|
|
2211
2210
|
import type { SendSmsInput, SendSmsResult } from "./types";
|
|
2212
2211
|
|
|
@@ -2258,13 +2257,13 @@ export async function sendSms(input: SendSmsInput): Promise<SendSmsResult> {
|
|
|
2258
2257
|
}
|
|
2259
2258
|
|
|
2260
2259
|
export type { SendSmsInput, SendSmsResult } from "./types";
|
|
2261
|
-
`}function
|
|
2262
|
-
`}}function
|
|
2263
|
-
`}async function
|
|
2264
|
-
`+t):
|
|
2260
|
+
`}function mc(e){switch(e){case"twilio":return ac();case"messagebird":return cc();case"plivo":return pc();case"aliyun-sms":return lc();case"tencent-sms":return dc();case"yunpian":return uc();case"none":return`export {};
|
|
2261
|
+
`}}function gc(e){let t={};for(let o of e.pkgs??[]){let r=oc[o];r&&(t[o]=r)}let n={name:nc,version:"0.1.0",private:!0,description:`Transactional SMS via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
|
|
2262
|
+
`}async function Ir(e,t,n="global"){if(t==="none")return;let o=Ar(t);if(!o)throw new Error(`Unknown SMS provider "${t}". Valid ids: ${Tt.map(i=>i.id).join(", ")}`);let r=Fe.join(e,"packages","sms");if(!Ae.existsSync(r))return;let s=Fe.join(r,"src");Ae.existsSync(s)&&Ae.rmSync(s,{recursive:!0,force:!0});try{Sn(Fe.join(r,"package.json"),gc(o)),Sn(Fe.join(s,"types.ts"),ic),Sn(Fe.join(s,"index.ts"),mc(o.id)),rc(e,sc(o))}catch(i){throw console.error(`Failed to apply SMS selection "${t}":`,i),new Error(`SMS scaffold for "${t}" failed \u2014 see stderr for details.`)}}import Be from"fs";import je from"path";var Ve="@nebutra/storage";function hn(e,t){Be.mkdirSync(je.dirname(e),{recursive:!0}),Be.writeFileSync(e,t)}function fc(e,t){let n=je.join(e,".env.example");Be.existsSync(n)?Be.appendFileSync(n,`
|
|
2263
|
+
`+t):Be.writeFileSync(n,t)}function yc(e){if(e.envVars.length===0)return"";let t=`# Storage provider: ${e.name}`,n=e.envVars.map(o=>`${o}=`).join(`
|
|
2265
2264
|
`);return`${t}
|
|
2266
2265
|
${n}
|
|
2267
|
-
`}var
|
|
2266
|
+
`}var Sc=`/**
|
|
2268
2267
|
* Inputs for the \`uploadFile\` wrapper. Keep this surface portable across
|
|
2269
2268
|
* providers \u2014 provider-specific options belong in the wrapper itself.
|
|
2270
2269
|
*/
|
|
@@ -2290,8 +2289,8 @@ export interface SignedUrlOptions {
|
|
|
2290
2289
|
operation?: "get" | "put";
|
|
2291
2290
|
contentType?: string;
|
|
2292
2291
|
}
|
|
2293
|
-
`;function
|
|
2294
|
-
* @${
|
|
2292
|
+
`;function hc(){return`/**
|
|
2293
|
+
* @${Ve.slice(1)} \u2014 Cloudflare R2 via the S3-compatible API.
|
|
2295
2294
|
*
|
|
2296
2295
|
* Docs: https://developers.cloudflare.com/r2/api/s3/api/
|
|
2297
2296
|
*/
|
|
@@ -2354,8 +2353,8 @@ export async function getSignedUrl(
|
|
|
2354
2353
|
}
|
|
2355
2354
|
|
|
2356
2355
|
export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
|
|
2357
|
-
`}function
|
|
2358
|
-
* @${
|
|
2356
|
+
`}function Ec(){return`/**
|
|
2357
|
+
* @${Ve.slice(1)} \u2014 AWS S3 wrapper.
|
|
2359
2358
|
*
|
|
2360
2359
|
* Docs: https://docs.aws.amazon.com/s3/
|
|
2361
2360
|
*/
|
|
@@ -2419,8 +2418,8 @@ export async function getSignedUrl(
|
|
|
2419
2418
|
}
|
|
2420
2419
|
|
|
2421
2420
|
export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
|
|
2422
|
-
`}function
|
|
2423
|
-
* @${
|
|
2421
|
+
`}function vc(){return`/**
|
|
2422
|
+
* @${Ve.slice(1)} \u2014 Supabase Storage wrapper.
|
|
2424
2423
|
*
|
|
2425
2424
|
* Docs: https://supabase.com/docs/guides/storage
|
|
2426
2425
|
*/
|
|
@@ -2482,8 +2481,8 @@ export async function getSignedUrl(
|
|
|
2482
2481
|
}
|
|
2483
2482
|
|
|
2484
2483
|
export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
|
|
2485
|
-
`}function
|
|
2486
|
-
* @${
|
|
2484
|
+
`}function bc(){return`/**
|
|
2485
|
+
* @${Ve.slice(1)} \u2014 \u963F\u91CC\u4E91 OSS wrapper via ali-oss.
|
|
2487
2486
|
*
|
|
2488
2487
|
* Docs: https://help.aliyun.com/product/31815.html
|
|
2489
2488
|
*/
|
|
@@ -2529,8 +2528,8 @@ export async function getSignedUrl(
|
|
|
2529
2528
|
}
|
|
2530
2529
|
|
|
2531
2530
|
export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
|
|
2532
|
-
`}function
|
|
2533
|
-
* @${
|
|
2531
|
+
`}function _c(){return`/**
|
|
2532
|
+
* @${Ve.slice(1)} \u2014 \u817E\u8BAF\u4E91 COS wrapper via cos-nodejs-sdk-v5.
|
|
2534
2533
|
*
|
|
2535
2534
|
* Docs: https://cloud.tencent.com/document/product/436
|
|
2536
2535
|
*/
|
|
@@ -2584,8 +2583,8 @@ export async function getSignedUrl(
|
|
|
2584
2583
|
}
|
|
2585
2584
|
|
|
2586
2585
|
export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
|
|
2587
|
-
`}function
|
|
2588
|
-
* @${
|
|
2586
|
+
`}function Pc(){return`/**
|
|
2587
|
+
* @${Ve.slice(1)} \u2014 \u4E03\u725B\u4E91 Kodo wrapper.
|
|
2589
2588
|
*
|
|
2590
2589
|
* Docs: https://developer.qiniu.com/kodo
|
|
2591
2590
|
*/
|
|
@@ -2652,9 +2651,9 @@ export async function getSignedUrl(
|
|
|
2652
2651
|
}
|
|
2653
2652
|
|
|
2654
2653
|
export type { UploadFileInput, UploadFileResult, SignedUrlOptions } from "./types";
|
|
2655
|
-
`}function
|
|
2656
|
-
`}}function
|
|
2657
|
-
`}async function
|
|
2654
|
+
`}function wc(e){switch(e){case"r2":return hc();case"s3":return Ec();case"supabase-storage":return vc();case"aliyun-oss":return bc();case"tencent-cos":return _c();case"qiniu":return Pc();case"none":return`export {};
|
|
2655
|
+
`}}function Ac(e){let t={};e.pkg&&e.pkgVersion&&(t[e.pkg]=e.pkgVersion),(e.id==="r2"||e.id==="s3")&&(t["@aws-sdk/s3-request-presigner"]="^3.658.0");let n={name:Ve,version:"0.1.0",private:!0,description:`Object storage via ${e.name}`,type:"module",main:"./dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},scripts:{build:"tsup",typecheck:"tsc --noEmit",clean:"rm -rf dist .turbo"},dependencies:t,devDependencies:{tsup:"^8.5.0",typescript:"catalog:"}};return JSON.stringify(n,null,2)+`
|
|
2656
|
+
`}async function Cr(e,t,n){if(t==="none")return;let o=Rn(t);if(!o)throw new Error(`Unknown storage provider "${t}". Valid ids: ${it.map(i=>i.id).join(", ")}`);let r=je.join(e,"packages","storage"),s=je.join(r,"src");Be.existsSync(s)&&Be.rmSync(s,{recursive:!0,force:!0}),hn(je.join(r,"package.json"),Ac(o)),hn(je.join(s,"types.ts"),Sc),hn(je.join(s,"index.ts"),wc(o.id)),fc(e,yc(o))}var Nt=[{id:"svix",name:"Svix",region:"global",envVars:["SVIX_API_TOKEN"],docs:"https://docs.svix.com",description:"Managed webhooks platform"},{id:"custom",name:"Custom (self-hosted)",region:"both",envVars:["WEBHOOK_SIGNING_SECRET"],docs:"",description:"Custom implementation with built-in package"},{id:"none",name:"None",region:"both",envVars:[],docs:"",description:""}];function xr(e){return Nt.find(t=>t.id===e)}var Eu=Nt.reduce((e,t)=>(e[t.region]||(e[t.region]=[]),e[t.region].push(t),e),{});async function Rr(e,t,n="global"){let o=xr(t);if(!o)throw new Error(`Unknown webhooks provider "${t}". Valid ids: ${Nt.map(r=>r.id).join(", ")}`);if(o.id==="none"){z(e,"webhooks");return}o.envVars.length>0&&oe(e,{category:"Webhooks",name:o.name,envVars:o.envVars,docs:o.docs}),re(e,"WEBHOOKS_PROVIDER",o.id)}import Ke from"fs";import mt from"path";function Ic(e){return`import { brand } from "@nebutra/brand/metadata";
|
|
2658
2657
|
import Link from "next/link";
|
|
2659
2658
|
|
|
2660
2659
|
export default function WelcomePage() {
|
|
@@ -2764,21 +2763,21 @@ function Step({
|
|
|
2764
2763
|
</li>
|
|
2765
2764
|
);
|
|
2766
2765
|
}
|
|
2767
|
-
`}function
|
|
2766
|
+
`}function Cc(e={}){return`
|
|
2768
2767
|
## What you can do next
|
|
2769
2768
|
|
|
2770
2769
|
${[e.apiKeys===!1?"- Manage API keys at `/settings/api-keys` (disabled \u2014 re-enable with `--api-keys=true`)":"- Manage API keys at `/settings/api-keys`",e.auditLog===!1?"- View audit log at `/settings/audit-log` (disabled \u2014 re-enable with `--audit-log=true`)":"- View audit log at `/settings/audit-log`","- Configure webhooks at `/settings/webhooks`",e.commandPalette===!1?"- Press \u2318K to open the command palette (disabled \u2014 re-enable with `--command-palette=true`)":"- Press \u2318K to open the command palette","- Edit notification preferences at `/settings/notifications`","- Export your data at `/settings/account/export`","- For China deployments, see `packages/ops/china-compliance/README.md`"].join(`
|
|
2771
2770
|
`)}
|
|
2772
|
-
`}function
|
|
2771
|
+
`}function xc(e=[]){return e.length===0?"":`
|
|
2773
2772
|
## Production readiness holds
|
|
2774
2773
|
|
|
2775
|
-
Do not enable these in production until
|
|
2774
|
+
Do not enable these in production until provider credentials, adapter wiring, and the integration contract are verified:
|
|
2776
2775
|
|
|
2777
|
-
${e.map(n=>{let o=
|
|
2776
|
+
${e.map(n=>{let o=Xe(n.status);return`- ${n.flag}=${n.provider} ${o} \u2014 ${he(n.status)}`}).join(`
|
|
2778
2777
|
`)}
|
|
2779
2778
|
|
|
2780
2779
|
Review the package readiness matrix before handoff: [docs/package-status.md](docs/package-status.md)
|
|
2781
|
-
`}function
|
|
2780
|
+
`}function Rc(e,t,n=[],o={}){return`# Next steps \u2014 ${e}
|
|
2782
2781
|
|
|
2783
2782
|
Region: ${t}
|
|
2784
2783
|
|
|
@@ -2804,24 +2803,24 @@ Your AI-native SaaS scaffold is ready. Complete these four steps to go from temp
|
|
|
2804
2803
|
\`\`\`
|
|
2805
2804
|
|
|
2806
2805
|
After setup, delete the welcome route at \`apps/web/src/app/[locale]/welcome/\`.
|
|
2807
|
-
${
|
|
2806
|
+
${Cc(o)}${xc(n)}
|
|
2808
2807
|
|
|
2809
2808
|
## Resources
|
|
2810
2809
|
|
|
2811
2810
|
- [Documentation](/docs)
|
|
2812
2811
|
- [GitHub](https://github.com/nebutra/nebutra-sailor)
|
|
2813
2812
|
- [Get free license (Individual/OPC)](https://nebutra.com/get-license)
|
|
2814
|
-
`}async function
|
|
2815
|
-
`)}function
|
|
2816
|
-
`))}}function
|
|
2813
|
+
`}async function kr(e,t){let{projectName:n,region:o,previewSelections:r=[],waveFeatures:s={}}=t;try{let i=mt.join(e,".sailor");Ke.existsSync(i)||Ke.mkdirSync(i,{recursive:!0}),Ke.writeFileSync(mt.join(i,"next-steps.md"),Rc(n,o,r,s))}catch(i){let a=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write .sailor/next-steps.md: ${a}`)}try{let i=mt.join(e,"apps","web");if(!Ke.existsSync(i))return;let a=mt.join(i,"src","app","[locale]","welcome");Ke.existsSync(a)||Ke.mkdirSync(a,{recursive:!0}),Ke.writeFileSync(mt.join(a,"page.tsx"),Ic(n))}catch(i){let a=i instanceof Error?i.message:String(i);console.warn(`[create-sailor] Failed to write welcome page: ${a}`)}}function l(e,t){e&&process.stdout.write(JSON.stringify(t)+`
|
|
2814
|
+
`)}function Tr(e){return e!==null&&typeof e=="object"&&"code"in e&&e.code==="ENOENT"}function Tc(e,t){for(let n of t)if(e)l(!0,{event:"warn",step:n.flag,provider:n.provider,packageStatus:n.status,message:he(n.status)});else{let o=Xe(n.status);process.stdout.write(gt.yellow(`\u26A0 ${n.flag}=${n.provider} ${o} \u2014 ${he(n.status)}
|
|
2815
|
+
`))}}function Nc(e,t,n){let o=$e.join(t,"packages/platform/db/prisma/schema.prisma"),r;try{r=Lt.readFileSync(o,"utf8")}catch(s){if(Tr(s)){l(e,{event:"step",step:"schema-prune",status:"skip"});return}let i=s instanceof Error?s.message:String(s);l(e,{event:"step",step:"schema-prune",status:"error",error:i});return}l(e,{event:"step",step:"schema-prune",status:"start"});try{let s=yn(r,n);Lt.writeFileSync(o,s),fn($e.join($e.dirname(o),"migrations"),n),l(e,{event:"step",step:"schema-prune",status:"ok"})}catch(s){let i=s instanceof Error?s.message:String(s);l(e,{event:"step",step:"schema-prune",status:"error",error:i})}}async function Nr(e){let{resolvedTarget:t,projectName:n,resolvedPm:o,opts:r,useJson:s,resolved:i,startedAt:a}=e,{region:c,orm:p,database:u,databaseHost:d,payment:_,paymentChoice:h,auth:f,socialLoginIds:E,aiProviders:S,deployTarget:m,docs:P,metering:G,billingMode:M,idp:ge,accessGate:pe,mcp:Z,waveToggles:j,previewSelections:K,config:C}=i,H={auth:f,payment:h,"billing-mode":M,idp:ge,template:"saas","access-gate":pe};l(s,{event:"step",step:"clone",status:"start"}),await Lo(t),l(s,{event:"step",step:"clone",status:"ok"}),l(s,{event:"step",step:"package",status:"start"}),await zo(t,n),l(s,{event:"step",step:"package",status:"ok"}),l(s,{event:"step",step:"config",status:"start"}),await co(t,C),l(s,{event:"step",step:"config",status:"ok"}),l(s,{event:"step",step:"governance-lints",status:"start"});let le=await Mo(t,C);l(s,{event:"step",step:"governance-lints",status:"ok",lints:le.lints}),l(s,{event:"step",step:"prune",status:"start"}),await cr(t,C),l(s,{event:"step",step:"prune",status:"ok"});{let v=$e.join(t,"packages/platform/db/prisma/schema.prisma"),k;try{k=Lt.readFileSync(v,"utf-8")}catch(I){if(Tr(I))l(s,{event:"step",step:"schema-prune",status:"skip"});else{let x=I instanceof Error?I.message:String(I);l(s,{event:"step",step:"schema-prune",status:"error",error:x})}}if(k!==void 0){l(s,{event:"step",step:"schema-prune",status:"start"});try{let I=yn(k,H);Lt.writeFileSync(v,I),fn($e.join($e.dirname(v),"migrations"),H),l(s,{event:"step",step:"schema-prune",status:"ok"})}catch(I){let x=I instanceof Error?I.message:String(I);l(s,{event:"step",step:"schema-prune",status:"error",error:x})}}}if(l(s,{event:"step",step:"auth",choice:f,status:"start"}),await zn(t,f),l(s,{event:"step",step:"auth",choice:f,status:"ok"}),E.length>0?(l(s,{event:"step",step:"social-login",providers:E,status:"start"}),await Qn(t,E,f),l(s,{event:"step",step:"social-login",providers:E,status:"ok"})):l(s,{event:"step",step:"social-login",status:"skip"}),l(s,{event:"step",step:"db",choice:u,status:"start"}),await uo(t,u,n),u!=="none"){let v=st(d);v&&(await mo(t,v,n),l(s,{event:"step",step:"db-host",choice:d,status:"ok"}))}if(l(s,{event:"step",step:"db",choice:u,status:"ok"}),p==="drizzle"){l(s,{event:"step",step:"orm",choice:"drizzle",status:"start"});let v=await Zo(t,"drizzle",u);l(s,{event:"step",step:"orm",choice:"drizzle",status:v.applied?"ok":"skip",...v.reason?{reason:v.reason}:{}})}if(l(s,{event:"step",step:"payment",choice:h,status:"start"}),await tr(t,h),l(s,{event:"step",step:"payment",choice:h,status:"ok"}),await vo(t,i.email,c),s&&l(!0,{event:"step",step:"email",choice:i.email,status:"ok"}),await Cr(t,i.storage,c),s&&l(!0,{event:"step",step:"storage",choice:i.storage,status:"ok"}),await Ho(t,i.monitoring,c),s&&l(!0,{event:"step",step:"monitoring",choice:i.monitoring,status:"ok"}),await Wn(t,i.analytics,c),s&&l(!0,{event:"step",step:"analytics",choice:i.analytics,status:"ok"}),await Ir(t,i.sms,c),s&&l(!0,{event:"step",step:"sms",choice:i.sms,status:"ok"}),await fr(t,i.queue,c),s&&l(!0,{event:"step",step:"queue",choice:i.queue,status:"ok"}),await Pr(t,i.search,c),s&&l(!0,{event:"step",step:"search",choice:i.search,status:"ok"}),await no(t,i.cache,c),s&&l(!0,{event:"step",step:"cache",choice:i.cache,status:"ok"}),await Xo(t,i.notifications,c),s&&l(!0,{event:"step",step:"notifications",choice:i.notifications,status:"ok"}),await Rr(t,i.webhooks,c),s&&l(!0,{event:"step",step:"webhooks",choice:i.webhooks,status:"ok"}),await io(t,i.cms,c),s&&l(!0,{event:"step",step:"cms",choice:i.cms,status:"ok"}),await Co(t,i.featureFlags,c),s&&l(!0,{event:"step",step:"feature-flags",choice:i.featureFlags,status:"ok"}),await ro(t,i.captcha,c),s&&l(!0,{event:"step",step:"captcha",choice:i.captcha,status:"ok"}),await Ko(t,Z),s&&l(!0,{event:"step",step:"mcp",mode:Z,status:"ok"}),await Yo(t,G,_),s&&l(!0,{event:"step",step:"metering",mode:G,status:"ok"}),l(s,{event:"step",step:"prune-wave-features",status:"start"}),pr(t,j),l(s,{event:"step",step:"prune-wave-features",status:"ok",toggles:j}),C.orm==="prisma"&&C.database!=="none"?Nc(s,t,H):l(s,{event:"step",step:"schema-prune",status:"skip"}),l(s,{event:"step",step:"billing-mode",choice:M,status:"ok"}),l(s,{event:"step",step:"idp",choice:ge,status:"ok"}),await ao(t,c),s&&l(!0,{event:"step",step:"compliance",region:c,status:"ok"}),await Ao(t),await wr(t,f),await kr(t,{projectName:n,region:c,previewSelections:K,waveFeatures:j}),C.aiMode!=="none"){l(s,{event:"step",step:"ai-providers",status:"start"});let v={providerIds:C.aiProviders,customEndpoint:C.customAiEndpoint},k=$e.join(t,"packages/ai/ai-providers/templates");await ir(t,v,k),l(s,{event:"step",step:"ai-providers",status:"ok"})}else l(s,{event:"step",step:"ai-providers",status:"skip"});l(s,{event:"step",step:"docs",status:"start"}),P!=="none"?(await yo(t,{framework:P,projectName:n}),l(s,{event:"step",step:"docs",framework:"fumadocs",requested:P,status:"ok"})):l(s,{event:"step",step:"docs",status:"skip"}),l(s,{event:"step",step:"deploy-target",status:"start"}),m!=="none"&&await Vn(t,m),await Bn(t,C.deployTargets),l(s,{event:"step",step:"deploy-target",status:"ok",targets:C.deployTargets});let w={databaseUrl:"postgresql://postgres:postgres@localhost:5432/nebutra",clerkPublishable:"",clerkSecret:""};l(s,{event:"step",step:"env",status:"start"}),await _o(t,w),l(s,{event:"step",step:"env",status:"ok"}),l(s,{event:"step",step:"scaffold-extras",status:"start"});let fe=await Sr(t,{projectName:n,withWorkflows:!!r.withWorkflows,withPythonBackend:!!r.withPythonBackend});l(s,{event:"step",step:"scaffold-extras",status:"ok",applied:fe.applied,skipped:fe.skipped}),l(s,{event:"step",step:"license",status:"start"});try{let v=Vo(t,{projectName:n,cliVersion:X});l(s,{event:"step",step:"license",status:"ok",tier:"independent",wrote:v.wrote}),s||process.stdout.write(gt.dim(` License: Nebutra-Sailor Independent Developer License (free for \u2264 1 FTE, < $1M ARR).
|
|
2817
2816
|
Upstream AGPL preserved as LICENSE-AGPL-REFERENCE.md.
|
|
2818
|
-
`))}catch(v){
|
|
2819
|
-
`));try{Ot(v,k,{cwd:t,stdio:
|
|
2820
|
-
`))}}else
|
|
2821
|
-
`))}}else
|
|
2822
|
-
`));return}
|
|
2817
|
+
`))}catch(v){l(s,{event:"step",step:"license",status:"warn",message:v instanceof Error?v.message:String(v)})}if(r.install!==!1){let v=o==="bun"?"bun":o,k=["install"];s?l(!0,{event:"step",step:"install",pm:o,status:"start"}):process.stdout.write(gt.dim(` Installing dependencies with ${o}\u2026
|
|
2818
|
+
`));try{Ot(v,k,{cwd:t,stdio:s?"ignore":"inherit"}),l(s,{event:"step",step:"install",status:"ok"})}catch(I){let x=I instanceof Error?I.message:String(I);s?l(!0,{event:"step",step:"install",status:"error",error:x}):process.stdout.write(gt.yellow(` \u26A0 install failed \u2014 run '${o} install' manually.
|
|
2819
|
+
`))}}else l(s,{event:"step",step:"install",status:"skip"});if(r.git!==!1){s&&l(!0,{event:"step",step:"git-init",status:"start"});try{Ot("git",["init","-q"],{cwd:t,stdio:"ignore"}),Ot("git",["add","-A"],{cwd:t,stdio:"ignore"}),Ot("git",["-c","user.email=you@example.com","-c","user.name=You","commit","-q","-m","chore: initial scaffold from create-sailor"],{cwd:t,stdio:"ignore"}),l(s,{event:"step",step:"git-init",status:"ok"})}catch(v){let k=v instanceof Error?v.message:String(v);s?l(!0,{event:"step",step:"git-init",status:"error",error:k}):process.stdout.write(gt.yellow(` \u26A0 git init skipped \u2014 not fatal.
|
|
2820
|
+
`))}}else l(s,{event:"step",step:"git-init",status:"skip"});let ye=Math.max(1,Math.round((Date.now()-a)/1e3));Xn({template_version:X,package_manager:o,region:c,auth:f,payment:h,ai_providers:S,deploy_target:m,duration_ms:Date.now()-a}),K.length>0&&Tc(s,K),s?l(!0,{event:"done",status:"ok",elapsedSec:ye,targetDir:t,previewSelections:K,waveFeatures:j}):qn({elapsedSec:ye,targetDir:t,skippedInstall:r.install===!1,previewSelections:K,waveFeatures:j});try{kc({pkg:{name:"create-sailor",version:X},updateCheckInterval:1e3*60*60*24}).notify({defer:!1,isGlobal:!0})}catch{}}import Oc from"cfonts";import Lc from"picocolors";function Or(){if(process.env.NO_COLOR||!process.stdout.isTTY){process.stdout.write([`Sailor v${X}`,"AI-Native SaaS Unicorn Template","by Nebutra \xB7 https://nebutra.com","",""].join(`
|
|
2821
|
+
`));return}Oc.say("Sailor",{font:"block",align:"left",colors:["#0033FE","#0BF1C3"],gradient:["#0033FE","#0BF1C3"],transitionGradient:!0,space:!1}),process.stdout.write(Lc.dim(` AI-Native SaaS Template \xB7 v${X} \xB7 nebutra.com
|
|
2823
2822
|
|
|
2824
|
-
`))}var
|
|
2823
|
+
`))}var Uc=`Usage: create-sailor [name] [options]
|
|
2825
2824
|
|
|
2826
2825
|
Arguments:
|
|
2827
2826
|
name project directory (default: ./my-saas-app)
|
|
@@ -2856,17 +2855,17 @@ Feature flags (region-based smart defaults):
|
|
|
2856
2855
|
--queue <id> qstash | bullmq | upstash | sqs | none [Foundation]
|
|
2857
2856
|
--search <id> meilisearch | typesense | algolia | pgvector | none [Foundation]
|
|
2858
2857
|
--cache <id> upstash-redis | vercel-kv | redis | dragonfly | none
|
|
2859
|
-
--notifications <id> novu | knock | custom | none
|
|
2860
|
-
--webhooks <id> svix | custom | none
|
|
2858
|
+
--notifications <id> novu | knock | custom | none
|
|
2859
|
+
--webhooks <id> svix | custom | none
|
|
2861
2860
|
--cms <id> sanity | contentful | strapi | none
|
|
2862
|
-
--feature-flags <id> vercel-flags | growthbook | configcat | none [
|
|
2861
|
+
--feature-flags <id> vercel-flags | growthbook | configcat | none [Foundation]
|
|
2863
2862
|
--captcha <id> turnstile | hcaptcha | aliyun-slide | none [WIP]
|
|
2864
2863
|
--billing-mode <mode> usage | seat | credits (default: usage)
|
|
2865
2864
|
--idp <id> clerk | oauth-server (default: clerk)
|
|
2866
2865
|
--access-gate <mode> none | invite (default: none)
|
|
2867
2866
|
|
|
2868
2867
|
Preview statuses:
|
|
2869
|
-
[Foundation] \u2014
|
|
2868
|
+
[Foundation] \u2014 core path works; provider credentials, adapter wiring, or integration verification still required
|
|
2870
2869
|
[WIP] \u2014 actively being built; do not use in production
|
|
2871
2870
|
See: https://github.com/Nebutra/Nebutra-Sailor/blob/main/docs/package-status.md
|
|
2872
2871
|
|
|
@@ -2892,10 +2891,10 @@ Examples:
|
|
|
2892
2891
|
$ npx create-sailor@latest my-app --region=cn --auth=clerk
|
|
2893
2892
|
$ npx create-sailor@latest my-app --region=hybrid --ai=openai,deepseek
|
|
2894
2893
|
$ npm create sailor@latest --dry-run --region=cn
|
|
2895
|
-
`;function
|
|
2896
|
-
`)}import{existsSync as
|
|
2897
|
-
`))}catch{}try{
|
|
2898
|
-
`)}function
|
|
2894
|
+
`;function Lr(){process.stdout.write(Uc)}import Ut from"picocolors";function Ur(){return!process.env.NO_COLOR&&!!process.stdout.isTTY}function Mc(e){let t=Ur()?"\u25B8":"->",n=`[${e.index}/${e.total}]`,o=e.label.padEnd(18," ");return Ur()?`${Ut.dim(n)} ${Ut.bold(o)} ${Ut.dim(t)} ${Ut.cyan(e.value)}`:`${n} ${o} ${t} ${e.value}`}function Mr(e){process.stdout.write(Mc(e)+`
|
|
2895
|
+
`)}import{existsSync as Dc,mkdirSync as Dr,writeFileSync as Fr}from"fs";import{homedir as jr,platform as Fc}from"os";import{join as ft}from"path";function jc(){if(Fc()==="win32"){let t=process.env.LOCALAPPDATA||ft(jr(),"AppData","Local");return ft(t,"nebutra")}let e=process.env.XDG_CONFIG_HOME;return e?ft(e,"nebutra"):ft(jr(),".config","nebutra")}function Bc(){let e=process.env.NEBUTRA_TELEMETRY;return e==="0"||e==="false"||e==="no"}function Br(){if(!process.stderr.isTTY||!process.stdin.isTTY||process.env.CI)return;let e=jc(),t=ft(e,"first-run-acked");try{if(Dc(t))return}catch{return}if(Bc()){try{Dr(e,{recursive:!0}),Fr(t,"")}catch{}return}let n=["[36m\u2139[0m Nebutra collects anonymous usage analytics to improve the scaffolder."," Opt out at any time: export NEBUTRA_TELEMETRY=0"," Privacy policy: https://nebutra.com/legal/cli-analytics",""];try{process.stderr.write(n.join(`
|
|
2896
|
+
`))}catch{}try{Dr(e,{recursive:!0}),Fr(t,"")}catch{}}function Ye(e,t){e&&process.stdout.write(JSON.stringify(t)+`
|
|
2897
|
+
`)}function Kc(e,t,n,o,r){let{region:s,orm:i,database:a,paymentChoice:c,docs:p,socialLoginIds:u,aiMode:d,aiProviders:_,customAiEndpoint:h,deployTarget:f,metering:E,payment:S,billingMode:m,idp:P,mcp:G,waveToggles:M,previewSelections:ge}=t,{email:pe,storage:Z,monitoring:j,analytics:K,sms:C,queue:H,search:le,cache:w,notifications:fe,webhooks:qe,cms:Ge,featureFlags:ye,captcha:v}=t,k=_.length,I=[`clone template \u2192 ${n}`,"write nebutra.config.json",`governance-lints \u2192 write governance.config.json + wire pnpm lint (no-raw-inputs${a!=="none"?" + repository-seam":""})`,`prune template (orm=${i}, i18n=${t.i18n})`,`region \u2192 ${s}`,`auth \u2192 ${t.auth==="none"?"skip (remove packages/auth)":`configure ${t.auth}`}`,...u.length>0?[`social-login \u2192 generate ${u.length} callback route${u.length===1?"":"s"} + SocialLoginButtons.tsx (${u.join(", ")})`]:[],`db \u2192 ${a==="none"?"skip (remove packages/db)":`configure Prisma for ${a}`}`,...a!=="none"?[`db-host \u2192 configure ${t.databaseHost}`]:[],`payment \u2192 ${c==="none"?"skip (remove packages/billing)":`configure ${c}`}`,...p!=="none"?[`docs \u2192 scaffold apps/docs (${p==="fumadocs"?"fumadocs":`${p} \u2192 fumadocs fallback`})`]:[],...k>0||h?[`ai-providers \u2192 generate ${d} registry seed + env (${k}${h?" + custom":""} provider${k===1&&!h?"":"s"})`]:[],...pe!=="none"?[`email \u2192 configure ${pe}`]:[],...Z!=="none"?[`storage \u2192 configure ${Z}`]:[],...j!=="none"?[`monitoring \u2192 configure ${j}`]:[],...K!=="none"?[`analytics \u2192 configure ${K}`]:[],...C!=="none"?[`sms \u2192 configure ${C}`]:[],...H!=="none"?[`queue \u2192 configure ${H}`]:[],...le!=="none"?[`search \u2192 configure ${le}`]:[],...w!=="none"?[`cache \u2192 configure ${w}`]:[],...fe!=="none"?[`notifications \u2192 configure ${fe}`]:[],...qe!=="none"?[`webhooks \u2192 configure ${qe}`]:[],...Ge!=="none"?[`cms \u2192 configure ${Ge}`]:[],...ye!=="none"?[`feature-flags \u2192 configure ${ye}`]:[],...v!=="none"?[`captcha \u2192 configure ${v}`]:[],`mcp \u2192 ${G==="on"?"enable MCP server":"remove packages/mcp"}`,`metering \u2192 ${E==="off"?"disabled":E==="auto"?S!=="none"?"enabled (auto: payment set)":"disabled (auto: no payment)":"enabled"}`,...m!=="usage"?[`billing-mode \u2192 ${m}`]:[],...P!=="clerk"?[`idp \u2192 ${P}`]:[],`cron-jobs \u2192 ${M.cronJobs?"enabled":"disabled"}`,`audit-log \u2192 ${M.auditLog?"enabled":"disabled"}`,`api-keys \u2192 ${M.apiKeys?"enabled":"disabled"}`,`command-palette \u2192 ${M.commandPalette?"enabled":"disabled"}`,`cookie-consent \u2192 ${M.cookieConsent?"enabled":"disabled"}`,`legal-pages \u2192 ${M.legalPages?"enabled":"disabled"}`,`china-compliance \u2192 ${M.chinaCompliance?"enabled (@nebutra/china-compliance + ICP footer)":"disabled"}`,`compliance \u2192 inject ${s} boilerplate (ICP/Cookie/AIGC/Privacy)`,"welcome \u2192 generate dev welcome page","env \u2192 generate random secrets (AUTH_SECRET, JWT_SECRET)","seed \u2192 generate prisma/seed.ts (1 admin + 3 tenants)",...f!=="none"?[`deploy \u2192 inject ${f} config`]:[],"inject .env.local",r.install===!1?"skip install":`run ${o} install`,r.git===!1?"skip git init":"run git init"];if(e){for(let x of I)Ye(!0,{event:"plan",action:x});for(let x of ge)Ye(!0,{event:"warn",step:x.flag,provider:x.provider,packageStatus:x.status});Ye(!0,{event:"done",dryRun:!0})}else{process.stdout.write(`
|
|
2899
2898
|
`+F.bold(`Dry run \u2014 planned actions:
|
|
2900
2899
|
`));for(let x of I)process.stdout.write(` \u2022 ${x}
|
|
2901
2900
|
`);if(ge.length>0){process.stdout.write(`
|
|
@@ -2903,7 +2902,7 @@ Examples:
|
|
|
2903
2902
|
`)));for(let x of ge)process.stdout.write(F.yellow(`\u26A0 ${x.flag}=${x.provider}
|
|
2904
2903
|
`))}process.stdout.write(F.dim(`
|
|
2905
2904
|
No files were written.
|
|
2906
|
-
`))}}async function
|
|
2905
|
+
`))}}async function $c(){let e=Cn();e.parse(process.argv);let t=e.opts(),[n]=e.args;t.help&&(Lr(),process.exit(0));let o=!!t.json,r=!!t.dryRun,s=!!t.yes,i=s||!process.stdin.isTTY;if(o||(Br(),Or()),Ye(o,{event:"start",version:X}),!t.pm)try{Vc("pnpm --version",{stdio:"ignore"})}catch{o||process.stderr.write(`
|
|
2907
2906
|
${F.red("\u2718")} ${F.bold("pnpm is required")} but was not found on PATH.
|
|
2908
2907
|
|
|
2909
2908
|
The scaffold uses pnpm workspaces + Turborepo. Install pnpm first:
|
|
@@ -2912,11 +2911,11 @@ The scaffold uses pnpm workspaces + Turborepo. Install pnpm first:
|
|
|
2912
2911
|
Then retry: ${F.cyan("pnpm dlx create-sailor@latest")}
|
|
2913
2912
|
(or pass ${F.dim("--pm=npm")} if you know workspace:* won't resolve in your setup)
|
|
2914
2913
|
|
|
2915
|
-
`)
|
|
2916
|
-
`)),process.exit(130)}});c=String(f.name)}let
|
|
2914
|
+
`),Ye(o,{event:"error",code:"PNPM_MISSING"}),process.exit(1)}let a=n??(s?"./my-saas-app":void 0),c;if(a)c=a;else if(i)c="./my-saas-app";else{let f=await ot.group({name:()=>ot.text({message:"Where should we create your project?",placeholder:"./my-saas-app",defaultValue:"./my-saas-app",validate:E=>{if(!E?.length)return"Please enter a path."}})},{onCancel:()=>{process.stdout.write(F.red(`\u2718 Cancelled
|
|
2915
|
+
`)),process.exit(130)}});c=String(f.name)}let p=Kr.basename(Kr.resolve(c)),u=t.pm??Nn(),d=await Yn(t,o),_=[["Project name",p],["Region",d.region],["Auth",d.auth],["Social login",d.socialLoginIds.length>0?d.socialLoginIds.map(f=>We.find(E=>E.id===f)?.name??f).join(", "):"none"],["ORM",d.orm],["Database",d.database],["Database Host",d.databaseHost],["Payment",d.paymentChoice],["AI topology",`${d.aiMode}${d.aiProviders.length>0?` (${d.aiProviders.join(", ")} seed)`:""}${d.customAiEndpoint?" + custom endpoint":""}`],["Email",d.email],["Storage",d.storage],["Monitoring",d.monitoring],["Analytics",d.analytics],["SMS",d.sms],["Deploy Target",d.deployTarget],["Docs Framework",d.docs],["Access gate",d.accessGate]];o?_.forEach(([f,E],S)=>{Ye(!0,{event:"step",step:f,value:E,index:S+1,total:_.length})}):_.forEach(([f,E],S)=>{Mr({index:S+1,total:_.length,label:f,value:E})}),r&&(Kc(o,d,c,u,t),process.exit(0));let h=async()=>{process.stdout.write(`
|
|
2917
2916
|
`+F.red(`\u2718 Cancelled
|
|
2918
|
-
`)),
|
|
2919
|
-
`))),process.exit(130)};process.on("SIGINT",h);try{await
|
|
2917
|
+
`)),Vr.existsSync(c)&&await ot.confirm({message:`Cleanup partial install at ${c}?`,initialValue:!0})===!0&&(Vr.rmSync(c,{recursive:!0,force:!0}),process.stdout.write(F.dim(` \u2713 Removed ${c}
|
|
2918
|
+
`))),process.exit(130)};process.on("SIGINT",h);try{await Nr({resolvedTarget:c,projectName:p,resolvedPm:u,opts:t,useJson:o,resolved:d,startedAt:Date.now()}),process.exit(0)}catch(f){let E=f instanceof Error?f.message:String(f);o?Ye(!0,{event:"error",message:E}):process.stdout.write(F.red(`
|
|
2920
2919
|
\u2718 Failed: ${E}
|
|
2921
|
-
`)),process.exit(1)}}
|
|
2920
|
+
`)),process.exit(1)}}$c().catch(e=>{process.stderr.write(String(e)+`
|
|
2922
2921
|
`),process.exit(1)});
|