create-better-t-stack 3.23.0 → 3.24.0
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 +26 -19
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +40 -112
- package/dist/index.mjs +1 -1
- package/dist/{src-COTG6r9y.mjs → src-SYbbb0XN.mjs} +70 -161
- package/dist/virtual.d.mts +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -29,21 +29,21 @@ Follow the prompts to configure your project or use the `--yes` flag for default
|
|
|
29
29
|
|
|
30
30
|
## Features
|
|
31
31
|
|
|
32
|
-
| Category | Options
|
|
33
|
-
| ------------------------ |
|
|
34
|
-
| **TypeScript** | End-to-end type safety across all parts of your application
|
|
35
|
-
| **Frontend** | • React with TanStack Router<br>• React with React Router<br>• React with TanStack Start (SSR)<br>• Next.js<br>• SvelteKit<br>• Nuxt (Vue)<br>• SolidJS<br>• React Native with NativeWind (via Expo)<br>• React Native with Unistyles (via Expo)<br>• None
|
|
36
|
-
| **Backend** | • Hono<br>• Express<br>• Elysia<br>• Next.js API routes<br>• Convex<br>• Fastify<br>• None
|
|
37
|
-
| **API Layer** | • tRPC (type-safe APIs)<br>• oRPC (OpenAPI-compatible type-safe APIs)<br>• None
|
|
38
|
-
| **Runtime** | • Bun<br>• Node.js<br>• Cloudflare Workers<br>• None
|
|
39
|
-
| **Database** | • SQLite<br>• PostgreSQL<br>• MySQL<br>• MongoDB<br>• None
|
|
40
|
-
| **ORM** | • Drizzle (TypeScript-first)<br>• Prisma (feature-rich)<br>• Mongoose (for MongoDB)<br>• None
|
|
41
|
-
| **Database Setup** | • Turso (SQLite)<br>• Cloudflare D1 (SQLite)<br>• Neon (PostgreSQL)<br>• Supabase (PostgreSQL)<br>• Prisma Postgres<br>• MongoDB Atlas<br>• None (manual setup)
|
|
42
|
-
| **Authentication** | Better-Auth (email/password, with more options coming soon)
|
|
43
|
-
| **Styling** | Tailwind CSS with a shared shadcn/ui package for React web apps
|
|
44
|
-
| **Addons** | • PWA support<br>• Tauri (desktop applications)<br>• Starlight (documentation
|
|
45
|
-
| **Examples** | • Todo app<br>• AI Chat interface (using Vercel AI SDK)
|
|
46
|
-
| **Developer Experience** | • Automatic Git initialization<br>• Package manager choice (npm, pnpm, bun)<br>• Automatic dependency installation
|
|
32
|
+
| Category | Options |
|
|
33
|
+
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
34
|
+
| **TypeScript** | End-to-end type safety across all parts of your application |
|
|
35
|
+
| **Frontend** | • React with TanStack Router<br>• React with React Router<br>• React with TanStack Start (SSR)<br>• Next.js<br>• SvelteKit<br>• Nuxt (Vue)<br>• SolidJS<br>• React Native with NativeWind (via Expo)<br>• React Native with Unistyles (via Expo)<br>• None |
|
|
36
|
+
| **Backend** | • Hono<br>• Express<br>• Elysia<br>• Next.js API routes<br>• Convex<br>• Fastify<br>• None |
|
|
37
|
+
| **API Layer** | • tRPC (type-safe APIs)<br>• oRPC (OpenAPI-compatible type-safe APIs)<br>• None |
|
|
38
|
+
| **Runtime** | • Bun<br>• Node.js<br>• Cloudflare Workers<br>• None |
|
|
39
|
+
| **Database** | • SQLite<br>• PostgreSQL<br>• MySQL<br>• MongoDB<br>• None |
|
|
40
|
+
| **ORM** | • Drizzle (TypeScript-first)<br>• Prisma (feature-rich)<br>• Mongoose (for MongoDB)<br>• None |
|
|
41
|
+
| **Database Setup** | • Turso (SQLite)<br>• Cloudflare D1 (SQLite)<br>• Neon (PostgreSQL)<br>• Supabase (PostgreSQL)<br>• Prisma Postgres<br>• MongoDB Atlas<br>• None (manual setup) |
|
|
42
|
+
| **Authentication** | Better-Auth (email/password, with more options coming soon) |
|
|
43
|
+
| **Styling** | Tailwind CSS with a shared shadcn/ui package for React web apps |
|
|
44
|
+
| **Addons** | • PWA support<br>• Tauri (desktop applications)<br>• Electrobun (lightweight desktop shell)<br>• Starlight and Fumadocs (documentation sites)<br>• Biome, Oxlint, Ultracite (linting and formatting)<br>• Lefthook, Husky (Git hooks)<br>• MCP, Skills (agent tooling)<br>• OpenTUI, WXT (platform extensions)<br>• Turborepo or Nx (monorepo orchestration) |
|
|
45
|
+
| **Examples** | • Todo app<br>• AI Chat interface (using Vercel AI SDK) |
|
|
46
|
+
| **Developer Experience** | • Automatic Git initialization<br>• Package manager choice (npm, pnpm, bun)<br>• Automatic dependency installation |
|
|
47
47
|
|
|
48
48
|
## Usage
|
|
49
49
|
|
|
@@ -60,7 +60,7 @@ Options:
|
|
|
60
60
|
--auth <provider> Authentication (better-auth, clerk, none)
|
|
61
61
|
--payments <provider> Payments provider (polar, none)
|
|
62
62
|
--frontend <types...> Frontend types (tanstack-router, react-router, tanstack-start, next, nuxt, svelte, solid, astro, native-bare, native-uniwind, native-unistyles, none)
|
|
63
|
-
--addons <types...> Additional addons (pwa, tauri, starlight, biome, lefthook, husky,
|
|
63
|
+
--addons <types...> Additional addons (pwa, tauri, electrobun, starlight, biome, lefthook, husky, mcp, turborepo, nx, fumadocs, ultracite, oxlint, opentui, wxt, skills, none)
|
|
64
64
|
--examples <types...> Examples to include (todo, ai, none)
|
|
65
65
|
--git Initialize git repository
|
|
66
66
|
--no-git Skip git initialization
|
|
@@ -98,7 +98,13 @@ create-better-t-stack schema --name cli
|
|
|
98
98
|
npx create-better-t-stack@latest mcp
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
To install Better T Stack into supported agent configs with `add-mcp` and avoid relying on a global CLI install:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npx -y add-mcp@latest "npx -y create-better-t-stack@latest mcp"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
When you scaffold with the `mcp` addon, Better T Stack itself can also be installed into supported agent configs through `add-mcp` using a package runner command instead of assuming a global CLI install. For Bun projects, the generated config uses the equivalent `bunx create-better-t-stack@latest mcp` server command inside `add-mcp`.
|
|
102
108
|
|
|
103
109
|
For MCP project creation, prefer `install: false`. Long dependency installs can exceed common MCP client request timeouts, so the safest flow is to scaffold first and run your package manager install command afterward in the project directory.
|
|
104
110
|
|
|
@@ -221,7 +227,7 @@ npx create-better-t-stack --frontend none --backend hono --api trpc --database n
|
|
|
221
227
|
|
|
222
228
|
- **Convex backend**: Requires `database`, `orm`, `api`, `runtime`, and `server-deploy` to be `none`; auth can be `better-auth`, `clerk`, or `none` depending frontend compatibility
|
|
223
229
|
- **Backend 'none'**: If selected, this option will force related options like API, ORM, database, authentication, and runtime to 'none'. Examples will also be disabled (set to none/empty).
|
|
224
|
-
- **Frontend 'none'**: Creates a backend-only project. When selected, PWA, Tauri, and certain examples may be disabled.
|
|
230
|
+
- **Frontend 'none'**: Creates a backend-only project. When selected, PWA, Tauri, Electrobun, and certain examples may be disabled.
|
|
225
231
|
- **API 'none'**: Disables tRPC/oRPC setup. Can be used with backend frameworks for REST APIs or custom API implementations.
|
|
226
232
|
- **Database 'none'**: Disables database setup and requires ORM to be `none`.
|
|
227
233
|
- **ORM 'none'**: Can be used when you want to handle database operations manually or use a different ORM.
|
|
@@ -231,7 +237,8 @@ npx create-better-t-stack --frontend none --backend hono --api trpc --database n
|
|
|
231
237
|
- **Examples 'none'**: Skips all example implementations (todo, AI chat).
|
|
232
238
|
- **Nuxt, Svelte, SolidJS, and Astro** frontends are only compatible with oRPC API layer
|
|
233
239
|
- **PWA support** requires TanStack Router, React Router, Next.js, or SolidJS
|
|
234
|
-
- **Tauri desktop app** requires TanStack Router, React Router, Nuxt,
|
|
240
|
+
- **Tauri desktop app** requires TanStack Router, React Router, TanStack Start, Next.js, Nuxt, SvelteKit, SolidJS, or Astro
|
|
241
|
+
- **Electrobun desktop app** requires TanStack Router, React Router, TanStack Start, Next.js, Nuxt, SvelteKit, SolidJS, or Astro. Desktop packaging uses static web assets, so SSR-first frontends need a static/export build before desktop builds will work.
|
|
235
242
|
- **AI example** is not compatible with Solid or Astro. With Convex backend, it also excludes Nuxt and Svelte.
|
|
236
243
|
|
|
237
244
|
## Project Structure
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { _ as types_exports, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as getLatestCLIVersion } from "./src-
|
|
2
|
+
import { _ as types_exports, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as getLatestCLIVersion } from "./src-SYbbb0XN.mjs";
|
|
3
3
|
import z from "zod";
|
|
4
4
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
5
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
package/dist/index.d.mts
CHANGED
|
@@ -209,11 +209,11 @@ declare const router: {
|
|
|
209
209
|
none: "none";
|
|
210
210
|
pwa: "pwa";
|
|
211
211
|
tauri: "tauri";
|
|
212
|
+
electrobun: "electrobun";
|
|
212
213
|
starlight: "starlight";
|
|
213
214
|
biome: "biome";
|
|
214
215
|
lefthook: "lefthook";
|
|
215
216
|
husky: "husky";
|
|
216
|
-
ruler: "ruler";
|
|
217
217
|
mcp: "mcp";
|
|
218
218
|
turborepo: "turborepo";
|
|
219
219
|
nx: "nx";
|
|
@@ -392,42 +392,6 @@ declare const router: {
|
|
|
392
392
|
goose: "goose";
|
|
393
393
|
}>>>;
|
|
394
394
|
}, z.core.$strict>>;
|
|
395
|
-
ruler: z.ZodOptional<z.ZodObject<{
|
|
396
|
-
assistants: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
397
|
-
antigravity: "antigravity";
|
|
398
|
-
cline: "cline";
|
|
399
|
-
cursor: "cursor";
|
|
400
|
-
codex: "codex";
|
|
401
|
-
opencode: "opencode";
|
|
402
|
-
"gemini-cli": "gemini-cli";
|
|
403
|
-
zed: "zed";
|
|
404
|
-
goose: "goose";
|
|
405
|
-
agentsmd: "agentsmd";
|
|
406
|
-
aider: "aider";
|
|
407
|
-
amazonqcli: "amazonqcli";
|
|
408
|
-
amp: "amp";
|
|
409
|
-
augmentcode: "augmentcode";
|
|
410
|
-
claude: "claude";
|
|
411
|
-
copilot: "copilot";
|
|
412
|
-
crush: "crush";
|
|
413
|
-
factory: "factory";
|
|
414
|
-
firebase: "firebase";
|
|
415
|
-
firebender: "firebender";
|
|
416
|
-
"jetbrains-ai": "jetbrains-ai";
|
|
417
|
-
jules: "jules";
|
|
418
|
-
junie: "junie";
|
|
419
|
-
kilocode: "kilocode";
|
|
420
|
-
kiro: "kiro";
|
|
421
|
-
mistral: "mistral";
|
|
422
|
-
openhands: "openhands";
|
|
423
|
-
pi: "pi";
|
|
424
|
-
qwen: "qwen";
|
|
425
|
-
roo: "roo";
|
|
426
|
-
trae: "trae";
|
|
427
|
-
warp: "warp";
|
|
428
|
-
windsurf: "windsurf";
|
|
429
|
-
}>>>;
|
|
430
|
-
}, z.core.$strict>>;
|
|
431
395
|
skills: z.ZodOptional<z.ZodObject<{
|
|
432
396
|
scope: z.ZodOptional<z.ZodEnum<{
|
|
433
397
|
project: "project";
|
|
@@ -442,14 +406,14 @@ declare const router: {
|
|
|
442
406
|
opencode: "opencode";
|
|
443
407
|
"gemini-cli": "gemini-cli";
|
|
444
408
|
goose: "goose";
|
|
445
|
-
amp: "amp";
|
|
446
|
-
openhands: "openhands";
|
|
447
|
-
pi: "pi";
|
|
448
|
-
roo: "roo";
|
|
449
|
-
trae: "trae";
|
|
450
|
-
windsurf: "windsurf";
|
|
451
409
|
"github-copilot": "github-copilot";
|
|
410
|
+
windsurf: "windsurf";
|
|
411
|
+
roo: "roo";
|
|
452
412
|
kilo: "kilo";
|
|
413
|
+
openhands: "openhands";
|
|
414
|
+
trae: "trae";
|
|
415
|
+
amp: "amp";
|
|
416
|
+
pi: "pi";
|
|
453
417
|
qoder: "qoder";
|
|
454
418
|
"qwen-code": "qwen-code";
|
|
455
419
|
"kiro-cli": "kiro-cli";
|
|
@@ -497,41 +461,41 @@ declare const router: {
|
|
|
497
461
|
cursor: "cursor";
|
|
498
462
|
vscode: "vscode";
|
|
499
463
|
zed: "zed";
|
|
500
|
-
kiro: "kiro";
|
|
501
|
-
trae: "trae";
|
|
502
464
|
windsurf: "windsurf";
|
|
465
|
+
trae: "trae";
|
|
466
|
+
kiro: "kiro";
|
|
503
467
|
}>>>;
|
|
504
468
|
agents: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
505
469
|
cline: "cline";
|
|
506
470
|
codex: "codex";
|
|
507
471
|
opencode: "opencode";
|
|
508
472
|
goose: "goose";
|
|
509
|
-
aider: "aider";
|
|
510
473
|
amp: "amp";
|
|
511
|
-
|
|
474
|
+
droid: "droid";
|
|
512
475
|
claude: "claude";
|
|
513
|
-
copilot: "copilot";
|
|
514
|
-
crush: "crush";
|
|
515
|
-
firebender: "firebender";
|
|
516
476
|
jules: "jules";
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
warp: "warp";
|
|
520
|
-
droid: "droid";
|
|
477
|
+
copilot: "copilot";
|
|
478
|
+
aider: "aider";
|
|
521
479
|
"firebase-studio": "firebase-studio";
|
|
522
480
|
"open-hands": "open-hands";
|
|
523
481
|
gemini: "gemini";
|
|
482
|
+
junie: "junie";
|
|
483
|
+
augmentcode: "augmentcode";
|
|
524
484
|
"kilo-code": "kilo-code";
|
|
525
485
|
"roo-code": "roo-code";
|
|
486
|
+
warp: "warp";
|
|
487
|
+
crush: "crush";
|
|
488
|
+
qwen: "qwen";
|
|
526
489
|
"amazon-q-cli": "amazon-q-cli";
|
|
490
|
+
firebender: "firebender";
|
|
527
491
|
"cursor-cli": "cursor-cli";
|
|
528
492
|
"mistral-vibe": "mistral-vibe";
|
|
529
493
|
vercel: "vercel";
|
|
530
494
|
}>>>;
|
|
531
495
|
hooks: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
532
496
|
cursor: "cursor";
|
|
533
|
-
claude: "claude";
|
|
534
497
|
windsurf: "windsurf";
|
|
498
|
+
claude: "claude";
|
|
535
499
|
}>>>;
|
|
536
500
|
}, z.core.$strict>>;
|
|
537
501
|
}, z.core.$strict>>;
|
|
@@ -597,11 +561,11 @@ declare const router: {
|
|
|
597
561
|
none: "none";
|
|
598
562
|
pwa: "pwa";
|
|
599
563
|
tauri: "tauri";
|
|
564
|
+
electrobun: "electrobun";
|
|
600
565
|
starlight: "starlight";
|
|
601
566
|
biome: "biome";
|
|
602
567
|
lefthook: "lefthook";
|
|
603
568
|
husky: "husky";
|
|
604
|
-
ruler: "ruler";
|
|
605
569
|
mcp: "mcp";
|
|
606
570
|
turborepo: "turborepo";
|
|
607
571
|
nx: "nx";
|
|
@@ -710,11 +674,11 @@ declare const router: {
|
|
|
710
674
|
none: "none";
|
|
711
675
|
pwa: "pwa";
|
|
712
676
|
tauri: "tauri";
|
|
677
|
+
electrobun: "electrobun";
|
|
713
678
|
starlight: "starlight";
|
|
714
679
|
biome: "biome";
|
|
715
680
|
lefthook: "lefthook";
|
|
716
681
|
husky: "husky";
|
|
717
|
-
ruler: "ruler";
|
|
718
682
|
mcp: "mcp";
|
|
719
683
|
turborepo: "turborepo";
|
|
720
684
|
nx: "nx";
|
|
@@ -738,11 +702,11 @@ declare const router: {
|
|
|
738
702
|
none: "none";
|
|
739
703
|
pwa: "pwa";
|
|
740
704
|
tauri: "tauri";
|
|
705
|
+
electrobun: "electrobun";
|
|
741
706
|
starlight: "starlight";
|
|
742
707
|
biome: "biome";
|
|
743
708
|
lefthook: "lefthook";
|
|
744
709
|
husky: "husky";
|
|
745
|
-
ruler: "ruler";
|
|
746
710
|
mcp: "mcp";
|
|
747
711
|
turborepo: "turborepo";
|
|
748
712
|
nx: "nx";
|
|
@@ -825,42 +789,6 @@ declare const router: {
|
|
|
825
789
|
goose: "goose";
|
|
826
790
|
}>>>;
|
|
827
791
|
}, z.core.$strict>>;
|
|
828
|
-
ruler: z.ZodOptional<z.ZodObject<{
|
|
829
|
-
assistants: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
830
|
-
antigravity: "antigravity";
|
|
831
|
-
cline: "cline";
|
|
832
|
-
cursor: "cursor";
|
|
833
|
-
codex: "codex";
|
|
834
|
-
opencode: "opencode";
|
|
835
|
-
"gemini-cli": "gemini-cli";
|
|
836
|
-
zed: "zed";
|
|
837
|
-
goose: "goose";
|
|
838
|
-
agentsmd: "agentsmd";
|
|
839
|
-
aider: "aider";
|
|
840
|
-
amazonqcli: "amazonqcli";
|
|
841
|
-
amp: "amp";
|
|
842
|
-
augmentcode: "augmentcode";
|
|
843
|
-
claude: "claude";
|
|
844
|
-
copilot: "copilot";
|
|
845
|
-
crush: "crush";
|
|
846
|
-
factory: "factory";
|
|
847
|
-
firebase: "firebase";
|
|
848
|
-
firebender: "firebender";
|
|
849
|
-
"jetbrains-ai": "jetbrains-ai";
|
|
850
|
-
jules: "jules";
|
|
851
|
-
junie: "junie";
|
|
852
|
-
kilocode: "kilocode";
|
|
853
|
-
kiro: "kiro";
|
|
854
|
-
mistral: "mistral";
|
|
855
|
-
openhands: "openhands";
|
|
856
|
-
pi: "pi";
|
|
857
|
-
qwen: "qwen";
|
|
858
|
-
roo: "roo";
|
|
859
|
-
trae: "trae";
|
|
860
|
-
warp: "warp";
|
|
861
|
-
windsurf: "windsurf";
|
|
862
|
-
}>>>;
|
|
863
|
-
}, z.core.$strict>>;
|
|
864
792
|
skills: z.ZodOptional<z.ZodObject<{
|
|
865
793
|
scope: z.ZodOptional<z.ZodEnum<{
|
|
866
794
|
project: "project";
|
|
@@ -875,14 +803,14 @@ declare const router: {
|
|
|
875
803
|
opencode: "opencode";
|
|
876
804
|
"gemini-cli": "gemini-cli";
|
|
877
805
|
goose: "goose";
|
|
878
|
-
amp: "amp";
|
|
879
|
-
openhands: "openhands";
|
|
880
|
-
pi: "pi";
|
|
881
|
-
roo: "roo";
|
|
882
|
-
trae: "trae";
|
|
883
|
-
windsurf: "windsurf";
|
|
884
806
|
"github-copilot": "github-copilot";
|
|
807
|
+
windsurf: "windsurf";
|
|
808
|
+
roo: "roo";
|
|
885
809
|
kilo: "kilo";
|
|
810
|
+
openhands: "openhands";
|
|
811
|
+
trae: "trae";
|
|
812
|
+
amp: "amp";
|
|
813
|
+
pi: "pi";
|
|
886
814
|
qoder: "qoder";
|
|
887
815
|
"qwen-code": "qwen-code";
|
|
888
816
|
"kiro-cli": "kiro-cli";
|
|
@@ -930,41 +858,41 @@ declare const router: {
|
|
|
930
858
|
cursor: "cursor";
|
|
931
859
|
vscode: "vscode";
|
|
932
860
|
zed: "zed";
|
|
933
|
-
kiro: "kiro";
|
|
934
|
-
trae: "trae";
|
|
935
861
|
windsurf: "windsurf";
|
|
862
|
+
trae: "trae";
|
|
863
|
+
kiro: "kiro";
|
|
936
864
|
}>>>;
|
|
937
865
|
agents: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
938
866
|
cline: "cline";
|
|
939
867
|
codex: "codex";
|
|
940
868
|
opencode: "opencode";
|
|
941
869
|
goose: "goose";
|
|
942
|
-
aider: "aider";
|
|
943
870
|
amp: "amp";
|
|
944
|
-
|
|
871
|
+
droid: "droid";
|
|
945
872
|
claude: "claude";
|
|
946
|
-
copilot: "copilot";
|
|
947
|
-
crush: "crush";
|
|
948
|
-
firebender: "firebender";
|
|
949
873
|
jules: "jules";
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
warp: "warp";
|
|
953
|
-
droid: "droid";
|
|
874
|
+
copilot: "copilot";
|
|
875
|
+
aider: "aider";
|
|
954
876
|
"firebase-studio": "firebase-studio";
|
|
955
877
|
"open-hands": "open-hands";
|
|
956
878
|
gemini: "gemini";
|
|
879
|
+
junie: "junie";
|
|
880
|
+
augmentcode: "augmentcode";
|
|
957
881
|
"kilo-code": "kilo-code";
|
|
958
882
|
"roo-code": "roo-code";
|
|
883
|
+
warp: "warp";
|
|
884
|
+
crush: "crush";
|
|
885
|
+
qwen: "qwen";
|
|
959
886
|
"amazon-q-cli": "amazon-q-cli";
|
|
887
|
+
firebender: "firebender";
|
|
960
888
|
"cursor-cli": "cursor-cli";
|
|
961
889
|
"mistral-vibe": "mistral-vibe";
|
|
962
890
|
vercel: "vercel";
|
|
963
891
|
}>>>;
|
|
964
892
|
hooks: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
965
893
|
cursor: "cursor";
|
|
966
|
-
claude: "claude";
|
|
967
894
|
windsurf: "windsurf";
|
|
895
|
+
claude: "claude";
|
|
968
896
|
}>>>;
|
|
969
897
|
}, z.core.$strict>>;
|
|
970
898
|
}, z.core.$strict>>;
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as ProjectCreationError, S as DirectoryConflictError, T as ValidationError, a as TEMPLATE_COUNT, b as CompatibilityError, c as builder, d as createVirtual, f as docs, g as sponsors, h as router, i as SchemaNameSchema, l as create, m as getSchemaResult, n as GeneratorError, o as VirtualFileSystem, p as generate, r as Result, s as add, t as EMBEDDED_TEMPLATES, u as createBtsCli, w as UserCancelledError, x as DatabaseSetupError, y as CLIError } from "./src-
|
|
2
|
+
import { C as ProjectCreationError, S as DirectoryConflictError, T as ValidationError, a as TEMPLATE_COUNT, b as CompatibilityError, c as builder, d as createVirtual, f as docs, g as sponsors, h as router, i as SchemaNameSchema, l as create, m as getSchemaResult, n as GeneratorError, o as VirtualFileSystem, p as generate, r as Result, s as add, t as EMBEDDED_TEMPLATES, u as createBtsCli, w as UserCancelledError, x as DatabaseSetupError, y as CLIError } from "./src-SYbbb0XN.mjs";
|
|
3
3
|
export { CLIError, CompatibilityError, DatabaseSetupError, DirectoryConflictError, EMBEDDED_TEMPLATES, GeneratorError, ProjectCreationError, Result, SchemaNameSchema, TEMPLATE_COUNT, UserCancelledError, ValidationError, VirtualFileSystem, add, builder, create, createBtsCli, createVirtual, docs, generate, getSchemaResult, router, sponsors };
|
|
@@ -5,12 +5,13 @@ import { os } from "@orpc/server";
|
|
|
5
5
|
import { Result, Result as Result$1, TaggedError } from "better-result";
|
|
6
6
|
import { createCli } from "trpc-cli";
|
|
7
7
|
import z from "zod";
|
|
8
|
-
import {
|
|
8
|
+
import { cancel, confirm, group, intro, isCancel, log, multiselect, outro, select, spinner, text } from "@clack/prompts";
|
|
9
9
|
import pc from "picocolors";
|
|
10
|
+
import path from "node:path";
|
|
10
11
|
import envPaths from "env-paths";
|
|
11
12
|
import fs from "fs-extra";
|
|
12
|
-
import path from "node:path";
|
|
13
13
|
import { fileURLToPath } from "node:url";
|
|
14
|
+
import { desktopWebFrontends as desktopWebFrontends$3 } from "@better-t-stack/types";
|
|
14
15
|
import { EMBEDDED_TEMPLATES, EMBEDDED_TEMPLATES as EMBEDDED_TEMPLATES$1, GeneratorError as GeneratorError$1, TEMPLATE_COUNT, VirtualFileSystem, VirtualFileSystem as VirtualFileSystem$1, dependencyVersionMap, generate, generate as generate$1, generateReproducibleCommand, processAddonTemplates, processAddonsDeps } from "@better-t-stack/template-generator";
|
|
15
16
|
import consola, { consola as consola$1 } from "consola";
|
|
16
17
|
import gradient from "gradient-string";
|
|
@@ -70,14 +71,8 @@ const ADDON_COMPATIBILITY = {
|
|
|
70
71
|
"solid",
|
|
71
72
|
"next"
|
|
72
73
|
],
|
|
73
|
-
tauri:
|
|
74
|
-
|
|
75
|
-
"react-router",
|
|
76
|
-
"nuxt",
|
|
77
|
-
"svelte",
|
|
78
|
-
"solid",
|
|
79
|
-
"next"
|
|
80
|
-
],
|
|
74
|
+
tauri: desktopWebFrontends$3,
|
|
75
|
+
electrobun: desktopWebFrontends$3,
|
|
81
76
|
biome: [],
|
|
82
77
|
husky: [],
|
|
83
78
|
lefthook: [],
|
|
@@ -85,7 +80,6 @@ const ADDON_COMPATIBILITY = {
|
|
|
85
80
|
nx: [],
|
|
86
81
|
starlight: [],
|
|
87
82
|
ultracite: [],
|
|
88
|
-
ruler: [],
|
|
89
83
|
mcp: [],
|
|
90
84
|
oxlint: [],
|
|
91
85
|
fumadocs: [],
|
|
@@ -1094,6 +1088,10 @@ function getAddonDisplay(addon) {
|
|
|
1094
1088
|
label = "Tauri";
|
|
1095
1089
|
hint = "Build native desktop apps from your web frontend";
|
|
1096
1090
|
break;
|
|
1091
|
+
case "electrobun":
|
|
1092
|
+
label = "Electrobun";
|
|
1093
|
+
hint = "Wrap web frontends in a lightweight desktop shell";
|
|
1094
|
+
break;
|
|
1097
1095
|
case "biome":
|
|
1098
1096
|
label = "Biome";
|
|
1099
1097
|
hint = "Format, lint, and more";
|
|
@@ -1106,10 +1104,6 @@ function getAddonDisplay(addon) {
|
|
|
1106
1104
|
label = "Ultracite";
|
|
1107
1105
|
hint = "Zero-config Biome preset with AI integration";
|
|
1108
1106
|
break;
|
|
1109
|
-
case "ruler":
|
|
1110
|
-
label = "Ruler";
|
|
1111
|
-
hint = "Centralize your AI rules";
|
|
1112
|
-
break;
|
|
1113
1107
|
case "lefthook":
|
|
1114
1108
|
label = "Lefthook";
|
|
1115
1109
|
hint = "Fast and powerful Git hooks manager";
|
|
@@ -1164,14 +1158,11 @@ const ADDON_GROUPS = {
|
|
|
1164
1158
|
"Platform Extensions": [
|
|
1165
1159
|
"pwa",
|
|
1166
1160
|
"tauri",
|
|
1161
|
+
"electrobun",
|
|
1167
1162
|
"opentui",
|
|
1168
1163
|
"wxt"
|
|
1169
1164
|
],
|
|
1170
|
-
"AI & Agent Tools": [
|
|
1171
|
-
"ruler",
|
|
1172
|
-
"skills",
|
|
1173
|
-
"mcp"
|
|
1174
|
-
]
|
|
1165
|
+
"AI & Agent Tools": ["skills", "mcp"]
|
|
1175
1166
|
};
|
|
1176
1167
|
function createGroupedOptions() {
|
|
1177
1168
|
return Object.fromEntries(Object.keys(ADDON_GROUPS).map((group) => [group, []]));
|
|
@@ -1939,118 +1930,6 @@ async function setupOxlint(projectDir, packageManager) {
|
|
|
1939
1930
|
});
|
|
1940
1931
|
}
|
|
1941
1932
|
//#endregion
|
|
1942
|
-
//#region src/helpers/addons/ruler-setup.ts
|
|
1943
|
-
const DEFAULT_ASSISTANTS = [
|
|
1944
|
-
"agentsmd",
|
|
1945
|
-
"claude",
|
|
1946
|
-
"codex",
|
|
1947
|
-
"cursor"
|
|
1948
|
-
];
|
|
1949
|
-
async function setupRuler(config) {
|
|
1950
|
-
if (shouldSkipExternalCommands()) return Result.ok(void 0);
|
|
1951
|
-
const { packageManager, projectDir } = config;
|
|
1952
|
-
cliLog.info("Setting up Ruler...");
|
|
1953
|
-
const rulerDir = path.join(projectDir, ".ruler");
|
|
1954
|
-
if (!await fs.pathExists(rulerDir)) {
|
|
1955
|
-
cliLog.error(pc.red("Ruler template directory not found. Please ensure ruler addon is properly installed."));
|
|
1956
|
-
return Result.ok(void 0);
|
|
1957
|
-
}
|
|
1958
|
-
const EDITORS = {
|
|
1959
|
-
agentsmd: { label: "Agents.md" },
|
|
1960
|
-
aider: { label: "Aider" },
|
|
1961
|
-
amazonqcli: { label: "Amazon Q CLI" },
|
|
1962
|
-
amp: { label: "AMP" },
|
|
1963
|
-
antigravity: { label: "Antigravity" },
|
|
1964
|
-
augmentcode: { label: "AugmentCode" },
|
|
1965
|
-
claude: { label: "Claude Code" },
|
|
1966
|
-
cline: { label: "Cline" },
|
|
1967
|
-
codex: { label: "OpenAI Codex CLI" },
|
|
1968
|
-
copilot: { label: "GitHub Copilot" },
|
|
1969
|
-
crush: { label: "Crush" },
|
|
1970
|
-
cursor: { label: "Cursor" },
|
|
1971
|
-
factory: { label: "Factory" },
|
|
1972
|
-
firebase: { label: "Firebase Studio" },
|
|
1973
|
-
firebender: { label: "Firebender" },
|
|
1974
|
-
"gemini-cli": { label: "Gemini CLI" },
|
|
1975
|
-
goose: { label: "Goose" },
|
|
1976
|
-
"jetbrains-ai": { label: "JetBrains AI" },
|
|
1977
|
-
jules: { label: "Jules" },
|
|
1978
|
-
junie: { label: "Junie" },
|
|
1979
|
-
kilocode: { label: "Kilo Code" },
|
|
1980
|
-
kiro: { label: "Kiro" },
|
|
1981
|
-
mistral: { label: "Mistral" },
|
|
1982
|
-
opencode: { label: "OpenCode" },
|
|
1983
|
-
openhands: { label: "Open Hands" },
|
|
1984
|
-
pi: { label: "Pi" },
|
|
1985
|
-
qwen: { label: "Qwen" },
|
|
1986
|
-
roo: { label: "RooCode" },
|
|
1987
|
-
trae: { label: "Trae AI" },
|
|
1988
|
-
warp: { label: "Warp" },
|
|
1989
|
-
windsurf: { label: "Windsurf" },
|
|
1990
|
-
zed: { label: "Zed" }
|
|
1991
|
-
};
|
|
1992
|
-
const configuredAssistants = config.addonOptions?.ruler?.assistants;
|
|
1993
|
-
let selectedEditors = configuredAssistants ? [...configuredAssistants] : [];
|
|
1994
|
-
if (selectedEditors.length === 0 && configuredAssistants === void 0) if (isSilent()) selectedEditors = [...DEFAULT_ASSISTANTS];
|
|
1995
|
-
else {
|
|
1996
|
-
const promptSelection = await autocompleteMultiselect({
|
|
1997
|
-
message: "Select AI assistants for Ruler",
|
|
1998
|
-
options: Object.entries(EDITORS).map(([key, v]) => ({
|
|
1999
|
-
value: key,
|
|
2000
|
-
label: v.label
|
|
2001
|
-
})),
|
|
2002
|
-
required: false
|
|
2003
|
-
});
|
|
2004
|
-
if (isCancel(promptSelection)) return userCancelled("Operation cancelled");
|
|
2005
|
-
selectedEditors = [...promptSelection];
|
|
2006
|
-
}
|
|
2007
|
-
if (selectedEditors.length === 0) {
|
|
2008
|
-
cliLog.info("No AI assistants selected. To apply rules later, run:");
|
|
2009
|
-
cliLog.info(pc.cyan(`${getPackageExecutionCommand(packageManager, "@intellectronica/ruler@latest apply --local-only")}`));
|
|
2010
|
-
return Result.ok(void 0);
|
|
2011
|
-
}
|
|
2012
|
-
const configFile = path.join(rulerDir, "ruler.toml");
|
|
2013
|
-
let updatedConfig = await fs.readFile(configFile, "utf-8");
|
|
2014
|
-
const defaultAgentsLine = `default_agents = [${selectedEditors.map((editor) => `"${editor}"`).join(", ")}]`;
|
|
2015
|
-
updatedConfig = updatedConfig.replace(/default_agents = \[\]/, defaultAgentsLine);
|
|
2016
|
-
await fs.writeFile(configFile, updatedConfig);
|
|
2017
|
-
await addRulerScriptToPackageJson(projectDir, packageManager);
|
|
2018
|
-
const s = createSpinner();
|
|
2019
|
-
s.start("Applying rules with Ruler...");
|
|
2020
|
-
const applyResult = await Result.tryPromise({
|
|
2021
|
-
try: async () => {
|
|
2022
|
-
const rulerApplyArgs = getPackageExecutionArgs(packageManager, `@intellectronica/ruler@latest apply --agents ${selectedEditors.join(",")} --local-only`);
|
|
2023
|
-
await $({
|
|
2024
|
-
cwd: projectDir,
|
|
2025
|
-
env: { CI: "true" }
|
|
2026
|
-
})`${rulerApplyArgs}`;
|
|
2027
|
-
},
|
|
2028
|
-
catch: (e) => new AddonSetupError({
|
|
2029
|
-
addon: "ruler",
|
|
2030
|
-
message: `Failed to apply rules: ${e instanceof Error ? e.message : String(e)}`,
|
|
2031
|
-
cause: e
|
|
2032
|
-
})
|
|
2033
|
-
});
|
|
2034
|
-
if (applyResult.isErr()) {
|
|
2035
|
-
s.stop(pc.red("Failed to apply rules"));
|
|
2036
|
-
return applyResult;
|
|
2037
|
-
}
|
|
2038
|
-
s.stop("Applied rules with Ruler");
|
|
2039
|
-
return Result.ok(void 0);
|
|
2040
|
-
}
|
|
2041
|
-
async function addRulerScriptToPackageJson(projectDir, packageManager) {
|
|
2042
|
-
const rootPackageJsonPath = path.join(projectDir, "package.json");
|
|
2043
|
-
if (!await fs.pathExists(rootPackageJsonPath)) {
|
|
2044
|
-
cliLog.warn("Root package.json not found, skipping ruler:apply script addition");
|
|
2045
|
-
return;
|
|
2046
|
-
}
|
|
2047
|
-
const packageJson = await fs.readJson(rootPackageJsonPath);
|
|
2048
|
-
if (!packageJson.scripts) packageJson.scripts = {};
|
|
2049
|
-
const rulerApplyCommand = getPackageExecutionCommand(packageManager, "@intellectronica/ruler@latest apply --local-only");
|
|
2050
|
-
packageJson.scripts["ruler:apply"] = rulerApplyCommand;
|
|
2051
|
-
await fs.writeJson(rootPackageJsonPath, packageJson, { spaces: 2 });
|
|
2052
|
-
}
|
|
2053
|
-
//#endregion
|
|
2054
1933
|
//#region src/helpers/addons/skills-setup.ts
|
|
2055
1934
|
const SKILL_SOURCES = {
|
|
2056
1935
|
"vercel-labs/agent-skills": { label: "Vercel Agent Skills" },
|
|
@@ -2442,14 +2321,32 @@ async function setupStarlight(config) {
|
|
|
2442
2321
|
}
|
|
2443
2322
|
//#endregion
|
|
2444
2323
|
//#region src/helpers/addons/tauri-setup.ts
|
|
2324
|
+
function getWebFrontend(frontend) {
|
|
2325
|
+
return frontend.find((value) => types_exports.desktopWebFrontends.includes(value));
|
|
2326
|
+
}
|
|
2327
|
+
function getTauriDevUrl(frontend) {
|
|
2328
|
+
switch (getWebFrontend(frontend)) {
|
|
2329
|
+
case "react-router":
|
|
2330
|
+
case "svelte": return "http://localhost:5173";
|
|
2331
|
+
case "astro": return "http://localhost:4321";
|
|
2332
|
+
default: return "http://localhost:3001";
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
function getTauriFrontendDist(frontend) {
|
|
2336
|
+
switch (getWebFrontend(frontend)) {
|
|
2337
|
+
case "react-router": return "../build/client";
|
|
2338
|
+
case "tanstack-start": return "../dist/client";
|
|
2339
|
+
case "next": return "../out";
|
|
2340
|
+
case "nuxt": return "../.output/public";
|
|
2341
|
+
case "svelte": return "../build";
|
|
2342
|
+
default: return "../dist";
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
function getTauriBeforeBuildCommand(packageManager, frontend) {
|
|
2346
|
+
return frontend.includes("nuxt") ? `${packageManager} run generate` : `${packageManager} run build`;
|
|
2347
|
+
}
|
|
2445
2348
|
function buildTauriInitArgs(config) {
|
|
2446
2349
|
const { packageManager, frontend, projectDir } = config;
|
|
2447
|
-
const hasReactRouter = frontend.includes("react-router");
|
|
2448
|
-
const hasNuxt = frontend.includes("nuxt");
|
|
2449
|
-
const hasSvelte = frontend.includes("svelte");
|
|
2450
|
-
const hasNext = frontend.includes("next");
|
|
2451
|
-
const devUrl = hasReactRouter || hasSvelte ? "http://localhost:5173" : hasNext ? "http://localhost:3001" : "http://localhost:3001";
|
|
2452
|
-
const frontendDist = hasNuxt ? "../.output/public" : hasSvelte ? "../build" : hasNext ? "../.next" : hasReactRouter ? "../build/client" : "../dist";
|
|
2453
2350
|
return [
|
|
2454
2351
|
...getPackageRunnerPrefix(packageManager),
|
|
2455
2352
|
"@tauri-apps/cli@latest",
|
|
@@ -2460,13 +2357,13 @@ function buildTauriInitArgs(config) {
|
|
|
2460
2357
|
"--window-title",
|
|
2461
2358
|
path.basename(projectDir),
|
|
2462
2359
|
"--frontend-dist",
|
|
2463
|
-
|
|
2360
|
+
getTauriFrontendDist(frontend),
|
|
2464
2361
|
"--dev-url",
|
|
2465
|
-
|
|
2362
|
+
getTauriDevUrl(frontend),
|
|
2466
2363
|
"--before-dev-command",
|
|
2467
2364
|
`${packageManager} run dev`,
|
|
2468
2365
|
"--before-build-command",
|
|
2469
|
-
|
|
2366
|
+
getTauriBeforeBuildCommand(packageManager, frontend)
|
|
2470
2367
|
];
|
|
2471
2368
|
}
|
|
2472
2369
|
async function setupTauri(config) {
|
|
@@ -2958,12 +2855,8 @@ async function runAddonStep(addon, step) {
|
|
|
2958
2855
|
}
|
|
2959
2856
|
async function setupAddons(config) {
|
|
2960
2857
|
const { addons, frontend, projectDir } = config;
|
|
2961
|
-
const
|
|
2962
|
-
|
|
2963
|
-
const hasSvelteFrontend = frontend.includes("svelte");
|
|
2964
|
-
const hasSolidFrontend = frontend.includes("solid");
|
|
2965
|
-
const hasNextFrontend = frontend.includes("next");
|
|
2966
|
-
if (addons.includes("tauri") && (hasReactWebFrontend || hasNuxtFrontend || hasSvelteFrontend || hasSolidFrontend || hasNextFrontend)) await runSetup(() => setupTauri(config));
|
|
2858
|
+
const hasWebFrontend = frontend.some((value) => types_exports.desktopWebFrontends.includes(value));
|
|
2859
|
+
if (addons.includes("tauri") && hasWebFrontend) await runSetup(() => setupTauri(config));
|
|
2967
2860
|
const hasUltracite = addons.includes("ultracite");
|
|
2968
2861
|
const hasBiome = addons.includes("biome");
|
|
2969
2862
|
const hasHusky = addons.includes("husky");
|
|
@@ -2989,7 +2882,6 @@ async function setupAddons(config) {
|
|
|
2989
2882
|
if (addons.includes("fumadocs")) await runSetup(() => setupFumadocs(config));
|
|
2990
2883
|
if (addons.includes("opentui")) await runSetup(() => setupTui(config));
|
|
2991
2884
|
if (addons.includes("wxt")) await runSetup(() => setupWxt(config));
|
|
2992
|
-
if (addons.includes("ruler")) await runSetup(() => setupRuler(config));
|
|
2993
2885
|
if (addons.includes("skills")) await runSetup(() => setupSkills(config));
|
|
2994
2886
|
if (addons.includes("mcp")) await runSetup(() => setupMcp(config));
|
|
2995
2887
|
}
|
|
@@ -5931,6 +5823,11 @@ async function setupTurso(config, cliInput) {
|
|
|
5931
5823
|
}
|
|
5932
5824
|
//#endregion
|
|
5933
5825
|
//#region src/helpers/core/db-setup.ts
|
|
5826
|
+
/**
|
|
5827
|
+
* Database setup - CLI-only operations
|
|
5828
|
+
* Calls external database provider CLIs (turso, neon, prisma-postgres, etc.)
|
|
5829
|
+
* Dependencies are handled by the generator's db-deps processor
|
|
5830
|
+
*/
|
|
5934
5831
|
async function setupDatabase(config, cliInput) {
|
|
5935
5832
|
const { database, dbSetup, backend, projectDir } = config;
|
|
5936
5833
|
if (backend === "convex" || database === "none") {
|
|
@@ -6050,6 +5947,18 @@ async function getDockerStatus(database) {
|
|
|
6050
5947
|
}
|
|
6051
5948
|
//#endregion
|
|
6052
5949
|
//#region src/helpers/core/post-installation.ts
|
|
5950
|
+
function getDesktopStaticBuildNote(frontend) {
|
|
5951
|
+
const staticBuildFrontends = new Map([
|
|
5952
|
+
["tanstack-start", "TanStack Start"],
|
|
5953
|
+
["next", "Next.js"],
|
|
5954
|
+
["nuxt", "Nuxt"],
|
|
5955
|
+
["svelte", "SvelteKit"],
|
|
5956
|
+
["astro", "Astro"]
|
|
5957
|
+
]);
|
|
5958
|
+
const staticBuildFrontend = frontend.find((value) => staticBuildFrontends.has(value));
|
|
5959
|
+
if (!staticBuildFrontend) return "";
|
|
5960
|
+
return `${pc.yellow("NOTE:")} Desktop builds package static web assets.\n ${staticBuildFrontends.get(staticBuildFrontend)} needs a static/export web build before desktop packaging will work.`;
|
|
5961
|
+
}
|
|
6053
5962
|
async function displayPostInstallInstructions(config) {
|
|
6054
5963
|
const { api, database, relativePath, packageManager, depsInstalled, orm, addons, runtime, frontend, backend, dbSetup, webDeploy, serverDeploy } = config;
|
|
6055
5964
|
const isConvex = backend === "convex";
|
|
@@ -6060,7 +5969,8 @@ async function displayPostInstallInstructions(config) {
|
|
|
6060
5969
|
const hasLefthook = addons?.includes("lefthook");
|
|
6061
5970
|
const hasGitHooksOrLinting = addons?.includes("husky") || addons?.includes("biome") || addons?.includes("lefthook") || addons?.includes("oxlint");
|
|
6062
5971
|
const databaseInstructions = !isConvex && database !== "none" ? await getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup, serverDeploy, backend) : "";
|
|
6063
|
-
const tauriInstructions = addons?.includes("tauri") ? getTauriInstructions(runCmd) : "";
|
|
5972
|
+
const tauriInstructions = addons?.includes("tauri") ? getTauriInstructions(runCmd, frontend) : "";
|
|
5973
|
+
const electrobunInstructions = addons?.includes("electrobun") ? getElectrobunInstructions(runCmd, frontend) : "";
|
|
6064
5974
|
const huskyInstructions = hasHusky ? getHuskyInstructions(runCmd) : "";
|
|
6065
5975
|
const lefthookInstructions = hasLefthook ? getLefthookInstructions(packageManager) : "";
|
|
6066
5976
|
const lintingInstructions = hasGitHooksOrLinting ? getLintingInstructions(runCmd) : "";
|
|
@@ -6070,19 +5980,12 @@ async function displayPostInstallInstructions(config) {
|
|
|
6070
5980
|
const clerkInstructions = isConvex && config.auth === "clerk" ? getClerkInstructions() : "";
|
|
6071
5981
|
const polarInstructions = config.payments === "polar" && config.auth === "better-auth" ? getPolarInstructions(backend) : "";
|
|
6072
5982
|
const alchemyDeployInstructions = getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend);
|
|
6073
|
-
const hasWeb = frontend?.some((f) =>
|
|
6074
|
-
"tanstack-router",
|
|
6075
|
-
"react-router",
|
|
6076
|
-
"next",
|
|
6077
|
-
"tanstack-start",
|
|
6078
|
-
"nuxt",
|
|
6079
|
-
"svelte",
|
|
6080
|
-
"solid"
|
|
6081
|
-
].includes(f));
|
|
5983
|
+
const hasWeb = frontend?.some((f) => types_exports.desktopWebFrontends.includes(f));
|
|
6082
5984
|
const hasNative = frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles");
|
|
6083
5985
|
const hasReactRouter = frontend?.includes("react-router");
|
|
6084
5986
|
const hasSvelte = frontend?.includes("svelte");
|
|
6085
|
-
const
|
|
5987
|
+
const hasAstro = frontend?.includes("astro");
|
|
5988
|
+
const webPort = hasReactRouter || hasSvelte ? "5173" : hasAstro ? "4321" : "3001";
|
|
6086
5989
|
const betterAuthConvexInstructions = isConvex && config.auth === "better-auth" ? getBetterAuthConvexInstructions(hasWeb ?? false, webPort, packageManager) : "";
|
|
6087
5990
|
const bunWebNativeWarning = packageManager === "bun" && hasNative && hasWeb ? getBunWebNativeWarning() : "";
|
|
6088
5991
|
const noOrmWarning = !isConvex && database !== "none" && orm === "none" ? getNoOrmWarning() : "";
|
|
@@ -6118,6 +6021,7 @@ async function displayPostInstallInstructions(config) {
|
|
|
6118
6021
|
if (nativeInstructions) output += `\n${nativeInstructions.trim()}\n`;
|
|
6119
6022
|
if (databaseInstructions) output += `\n${databaseInstructions.trim()}\n`;
|
|
6120
6023
|
if (tauriInstructions) output += `\n${tauriInstructions.trim()}\n`;
|
|
6024
|
+
if (electrobunInstructions) output += `\n${electrobunInstructions.trim()}\n`;
|
|
6121
6025
|
if (huskyInstructions) output += `\n${huskyInstructions.trim()}\n`;
|
|
6122
6026
|
if (lefthookInstructions) output += `\n${lefthookInstructions.trim()}\n`;
|
|
6123
6027
|
if (lintingInstructions) output += `\n${lintingInstructions.trim()}\n`;
|
|
@@ -6194,8 +6098,13 @@ async function getDatabaseInstructions(database, orm, runCmd, _runtime, dbSetup,
|
|
|
6194
6098
|
} else if (orm === "none") instructions.push(`${pc.yellow("NOTE:")} Manual database schema setup\n required.`);
|
|
6195
6099
|
return instructions.length ? `${pc.bold("Database commands:")}\n${instructions.join("\n")}` : "";
|
|
6196
6100
|
}
|
|
6197
|
-
function getTauriInstructions(runCmd) {
|
|
6198
|
-
|
|
6101
|
+
function getTauriInstructions(runCmd, frontend) {
|
|
6102
|
+
const staticBuildNote = getDesktopStaticBuildNote(frontend);
|
|
6103
|
+
return `\n${pc.bold("Desktop app with Tauri:")}\n${pc.cyan("•")} Start desktop app: ${`cd apps/web && ${runCmd} desktop:dev`}\n${pc.cyan("•")} Build desktop app: ${`cd apps/web && ${runCmd} desktop:build`}\n${pc.yellow("NOTE:")} Tauri requires Rust and platform-specific dependencies.\n See: https://v2.tauri.app/start/prerequisites/${staticBuildNote ? `\n${staticBuildNote}` : ""}`;
|
|
6104
|
+
}
|
|
6105
|
+
function getElectrobunInstructions(runCmd, frontend) {
|
|
6106
|
+
const staticBuildNote = getDesktopStaticBuildNote(frontend);
|
|
6107
|
+
return `\n${pc.bold("Desktop app with Electrobun:")}\n${pc.cyan("•")} Start desktop app with HMR: ${`${runCmd} dev:desktop`}\n${pc.cyan("•")} Build stable desktop app (DMG/App): ${`${runCmd} build:desktop`}\n${pc.cyan("•")} Build canary desktop app: ${`${runCmd} build:desktop:canary`}\n${pc.yellow("NOTE:")} Electrobun wraps your web frontend in a desktop shell.\n See: https://blackboard.sh/electrobun/docs/${staticBuildNote ? `\n${staticBuildNote}` : ""}`;
|
|
6199
6108
|
}
|
|
6200
6109
|
function getPwaInstructions() {
|
|
6201
6110
|
return `\n${pc.bold("PWA with React Router v7:")}\n${pc.yellow("NOTE:")} There is a known compatibility issue between VitePWA\n and React Router v7. See:\n https://github.com/vite-pwa/vite-plugin-pwa/issues/809`;
|
package/dist/virtual.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Result } from "better-result";
|
|
3
|
-
import { EMBEDDED_TEMPLATES, GeneratorError, GeneratorOptions, TEMPLATE_COUNT, VirtualDirectory, VirtualFile, VirtualFileSystem, VirtualFileTree, VirtualNode, generate } from "@better-t-stack/template-generator";
|
|
4
3
|
import { API, Addons, Auth, Backend, Database, DatabaseSetup, Examples, Frontend, ORM, PackageManager, Payments, ProjectConfig, Runtime, ServerDeploy, WebDeploy } from "@better-t-stack/types";
|
|
4
|
+
import { EMBEDDED_TEMPLATES, GeneratorError, GeneratorOptions, TEMPLATE_COUNT, VirtualDirectory, VirtualFile, VirtualFileSystem, VirtualFileTree, VirtualNode, generate } from "@better-t-stack/template-generator";
|
|
5
5
|
export { type API, type Addons, type Auth, type Backend, type Database, type DatabaseSetup, EMBEDDED_TEMPLATES, type Examples, type Frontend, GeneratorError, type GeneratorOptions, type ORM, type PackageManager, type Payments, type ProjectConfig, Result, type Runtime, type ServerDeploy, TEMPLATE_COUNT, type VirtualDirectory, type VirtualFile, VirtualFileSystem, type VirtualFileTree, type VirtualNode, type WebDeploy, generate };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.24.0",
|
|
4
4
|
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"better-auth",
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"prepublishOnly": "npm run build"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@better-t-stack/template-generator": "^3.
|
|
74
|
-
"@better-t-stack/types": "^3.
|
|
73
|
+
"@better-t-stack/template-generator": "^3.24.0",
|
|
74
|
+
"@better-t-stack/types": "^3.24.0",
|
|
75
75
|
"@clack/core": "^1.1.0",
|
|
76
76
|
"@clack/prompts": "^1.1.0",
|
|
77
77
|
"@modelcontextprotocol/sdk": "1.27.1",
|