create-newt-app 0.23.3 → 0.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.
Files changed (2) hide show
  1. package/dist/index.js +1055 -272
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import chalk from "chalk";
7
7
  // package.json
8
8
  var package_default = {
9
9
  name: "create-newt-app",
10
- version: "0.23.3",
10
+ version: "0.24.0",
11
11
  license: "MIT",
12
12
  private: false,
13
13
  type: "module",
@@ -21,7 +21,8 @@ var package_default = {
21
21
  build: "tsup",
22
22
  "build:watch": "tsup --watch",
23
23
  dev: "tsup --watch",
24
- test: "vitest run"
24
+ test: "vitest run",
25
+ typecheck: "tsc --noEmit"
25
26
  },
26
27
  dependencies: {
27
28
  "@clack/prompts": "^0.11.0",
@@ -63,8 +64,9 @@ var package_json_default = {
63
64
  "db:generate": "turbo run generate"
64
65
  },
65
66
  "devDependencies": {
66
- "turbo": "^2.8.16",
67
- "typescript": "6.0.2"
67
+ "@types/node": "<%= versions["@types/node"] %>",
68
+ "turbo": "<%= versions.turbo %>",
69
+ "typescript": "<%= versions.typescript %>"
68
70
  },
69
71
  "packageManager": "pnpm@9.0.0",
70
72
  "engines": {
@@ -117,15 +119,6 @@ yarn-error.log*
117
119
  *.pem`
118
120
  };
119
121
 
120
- // src/templates/root/templates/prettierrc.ts
121
- var prettierrc_default = {
122
- filename: ".prettierrc",
123
- template: `{
124
- "singleQuote": true,
125
- "trailingComma": "all"
126
- }`
127
- };
128
-
129
122
  // src/templates/root/templates/dockerignore.ts
130
123
  var dockerignore_default = {
131
124
  filename: ".dockerignore",
@@ -147,6 +140,7 @@ var npmrc_default = {
147
140
 
148
141
  // src/templates/root/templates/turbo-json.ts
149
142
  var turbo_json_default = {
143
+ when: (s) => s.deployment !== "standalone" && s.deployment !== "custom-server",
150
144
  filename: "turbo.json",
151
145
  template: `{
152
146
  "$schema": "https://turborepo.dev/schema.json",
@@ -250,7 +244,6 @@ var root = {
250
244
  templates: [
251
245
  package_json_default,
252
246
  gitignore_default,
253
- prettierrc_default,
254
247
  dockerignore_default,
255
248
  npmrc_default,
256
249
  turbo_json_default,
@@ -265,6 +258,7 @@ var root_default = root;
265
258
 
266
259
  // src/templates/web/templates/package-json.ts
267
260
  var package_json_default2 = {
261
+ when: (s) => !s.nestDiOnly && s.deployment !== "custom-server",
268
262
  filename: "apps/web/package.json",
269
263
  template: `{
270
264
  "name": "web",
@@ -280,22 +274,22 @@ var package_json_default2 = {
280
274
  "dependencies": {
281
275
  "@<%= projectName %>/auth": "workspace:*",
282
276
  "@<%= projectName %>/ui": "workspace:*",
283
- "@tailwindcss/postcss": "^4.2.1",
284
- "dotenv": "^17.3.1",
285
- "@tanstack/react-form": "^1.28.5",
286
- "@tanstack/react-query": "^5.90.21",
287
- "better-auth": "^1.2.8",
288
- "next": "16.2.10",
289
- "react": "^19.2.4",
290
- "react-dom": "^19.2.4",
291
- "tailwindcss": "^4.2.1"
277
+ "@tailwindcss/postcss": "<%= versions["@tailwindcss/postcss"] %>",
278
+ "dotenv": "<%= versions.dotenv %>",
279
+ "@tanstack/react-form": "<%= versions["@tanstack/react-form"] %>",
280
+ "@tanstack/react-query": "<%= versions["@tanstack/react-query"] %>",
281
+ "better-auth": "<%= versions["better-auth"] %>",
282
+ "next": "<%= versions.next %>",
283
+ "react": "<%= versions.react %>",
284
+ "react-dom": "<%= versions["react-dom"] %>",
285
+ "tailwindcss": "<%= versions.tailwindcss %>"
292
286
  },
293
287
  "devDependencies": {
294
288
  "@<%= projectName %>/typescript-config": "workspace:*",
295
- "@types/node": "^22.15.3",
296
- "@types/react": "19.2.14",
297
- "@types/react-dom": "19.2.3",
298
- "typescript": "6.0.2"
289
+ "@types/node": "<%= versions["@types/node"] %>",
290
+ "@types/react": "<%= versions["@types/react"] %>",
291
+ "@types/react-dom": "<%= versions["@types/react-dom"] %>",
292
+ "typescript": "<%= versions.typescript %>"
299
293
  }
300
294
  }`
301
295
  };
@@ -384,6 +378,7 @@ Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/bui
384
378
 
385
379
  // src/templates/web/templates/next-config.ts
386
380
  var next_config_default = {
381
+ when: (s) => s.deployment === "none" && !s.nestDiOnly,
387
382
  filename: "apps/web/next.config.js",
388
383
  template: `import dotenv from 'dotenv';
389
384
  import { resolve } from 'path';
@@ -415,6 +410,7 @@ var postcss_config_default = {
415
410
 
416
411
  // src/templates/web/templates/tsconfig.ts
417
412
  var tsconfig_default = {
413
+ when: (s) => !s.nestDiOnly && s.deployment !== "custom-server",
418
414
  filename: "apps/web/tsconfig.json",
419
415
  template: `{
420
416
  "extends": "@<%= projectName %>/typescript-config/nextjs.json",
@@ -442,6 +438,7 @@ var tsconfig_default = {
442
438
 
443
439
  // src/templates/web/templates/layout.ts
444
440
  var layout_default = {
441
+ when: (s) => !s.shadcn,
445
442
  filename: "apps/web/app/layout.tsx",
446
443
  template: `import type { Metadata } from "next";
447
444
  import localFont from "next/font/local";
@@ -486,6 +483,7 @@ export default function RootLayout({
486
483
 
487
484
  // src/templates/web/templates/page.ts
488
485
  var page_default = {
486
+ when: (s) => !s.todoExample && !s.shadcn,
489
487
  filename: "apps/web/app/page.tsx",
490
488
  template: `'use client';
491
489
 
@@ -575,6 +573,7 @@ export default function Home() {
575
573
 
576
574
  // src/templates/web/templates/providers.ts
577
575
  var providers_default = {
576
+ when: (s) => !s.shadcn,
578
577
  filename: "apps/web/app/providers.tsx",
579
578
  template: `'use client';
580
579
 
@@ -589,6 +588,7 @@ export default function Providers({ children }: { children: React.ReactNode }) {
589
588
 
590
589
  // src/templates/web/templates/auth-form.ts
591
590
  var auth_form_default = {
591
+ when: (s) => !s.shadcn,
592
592
  filename: "apps/web/app/auth-form.tsx",
593
593
  template: `'use client';
594
594
 
@@ -797,6 +797,7 @@ var web_default = web;
797
797
 
798
798
  // src/templates/api/templates/package-json.ts
799
799
  var package_json_default3 = {
800
+ when: (s) => !s.nestDiOnly && s.deployment !== "spa" && s.deployment !== "custom-server",
800
801
  filename: "apps/api/package.json",
801
802
  template: `{
802
803
  "name": "api",
@@ -814,27 +815,27 @@ var package_json_default3 = {
814
815
  "start:prod": "node dist/main"
815
816
  },
816
817
  "dependencies": {
817
- "@nestjs/common": "^11.0.1",
818
- "@nestjs/core": "^11.0.1",
819
- "@nestjs/platform-express": "^11.0.1",
818
+ "@nestjs/common": "<%= versions["@nestjs/common"] %>",
819
+ "@nestjs/core": "<%= versions["@nestjs/core"] %>",
820
+ "@nestjs/platform-express": "<%= versions["@nestjs/platform-express"] %>",
820
821
  "@<%= projectName %>/auth": "workspace:*",
821
822
  "@<%= projectName %>/db": "workspace:*",
822
- "@thallesp/nestjs-better-auth": "^2.5.1",
823
- "dotenv": "^17.3.1",
824
- "reflect-metadata": "^0.2.2",
825
- "rxjs": "^7.8.1"
823
+ "@thallesp/nestjs-better-auth": "<%= versions["@thallesp/nestjs-better-auth"] %>",
824
+ "dotenv": "<%= versions.dotenv %>",
825
+ "reflect-metadata": "<%= versions["reflect-metadata"] %>",
826
+ "rxjs": "<%= versions.rxjs %>"
826
827
  },
827
828
  "devDependencies": {
828
- "@nestjs/cli": "^11.0.0",
829
- "@nestjs/schematics": "^11.0.0",
830
- "@nestjs/testing": "^11.0.1",
831
- "@types/express": "^5.0.0",
832
- "@types/node": "^22.10.7",
833
- "@types/supertest": "^6.0.2",
834
- "supertest": "^7.0.0",
835
- "ts-node": "^10.9.2",
836
- "tsconfig-paths": "^4.2.0",
837
- "typescript": "6.0.2"
829
+ "@nestjs/cli": "<%= versions["@nestjs/cli"] %>",
830
+ "@nestjs/schematics": "<%= versions["@nestjs/schematics"] %>",
831
+ "@nestjs/testing": "<%= versions["@nestjs/testing"] %>",
832
+ "@types/express": "<%= versions["@types/express"] %>",
833
+ "@types/node": "<%= versions["@types/node"] %>",
834
+ "@types/supertest": "<%= versions["@types/supertest"] %>",
835
+ "supertest": "<%= versions.supertest %>",
836
+ "ts-node": "<%= versions["ts-node"] %>",
837
+ "tsconfig-paths": "<%= versions["tsconfig-paths"] %>",
838
+ "typescript": "<%= versions.typescript %>"
838
839
  }
839
840
  }`
840
841
  };
@@ -854,6 +855,7 @@ var nest_cli_default = {
854
855
 
855
856
  // src/templates/api/templates/tsconfig.ts
856
857
  var tsconfig_default2 = {
858
+ when: (s) => !s.nestDiOnly,
857
859
  filename: "apps/api/tsconfig.json",
858
860
  template: `{
859
861
  "compilerOptions": {
@@ -894,6 +896,7 @@ var tsconfig_build_default = {
894
896
 
895
897
  // src/templates/api/templates/app-module.ts
896
898
  var app_module_default = {
899
+ when: (s) => s.nestDiOnly && !s.todoExample,
897
900
  filename: "apps/api/src/app.module.ts",
898
901
  template: `import { Module } from '@nestjs/common';
899
902
  import { AppService } from './app.service';
@@ -988,13 +991,13 @@ var package_json_default4 = {
988
991
  },
989
992
  "dependencies": {
990
993
  "@<%= projectName %>/db": "workspace:*",
991
- "auth": "^1.5.5",
992
- "better-auth": "^1.2.8"
994
+ "auth": "<%= versions.auth %>",
995
+ "better-auth": "<%= versions["better-auth"] %>"
993
996
  },
994
997
  "devDependencies": {
995
998
  "@<%= projectName %>/typescript-config": "workspace:*",
996
- "dotenv-cli": "^11.0.0",
997
- "typescript": "6.0.2"
999
+ "dotenv-cli": "<%= versions["dotenv-cli"] %>",
1000
+ "typescript": "<%= versions.typescript %>"
998
1001
  }
999
1002
  }`
1000
1003
  };
@@ -1060,6 +1063,7 @@ var tsconfig_default4 = {
1060
1063
 
1061
1064
  // src/templates/db/templates/src-schema.ts
1062
1065
  var src_schema_default = {
1066
+ when: (s) => !s.todoExample,
1063
1067
  filename: "packages/db/src/schema.ts",
1064
1068
  template: `<% const date = database === 'postgres' ? 'Date' : 'string'; const bool = database === 'postgres' ? 'boolean' : 'number'; -%>
1065
1069
  export interface UserTable {
@@ -1229,15 +1233,15 @@ var package_json_sqlite_default = {
1229
1233
  "make": "tsx scripts/new-migration.ts"
1230
1234
  },
1231
1235
  "dependencies": {
1232
- "better-sqlite3": "^12.11.1",
1233
- "kysely": "^0.28.2"
1236
+ "better-sqlite3": "<%= versions["better-sqlite3"] %>",
1237
+ "kysely": "<%= versions.kysely %>"
1234
1238
  },
1235
1239
  "devDependencies": {
1236
1240
  "@<%= projectName %>/typescript-config": "workspace:*",
1237
- "@types/better-sqlite3": "^7.6.13",
1238
- "dotenv-cli": "^11.0.0",
1239
- "tsx": "^4.19.2",
1240
- "typescript": "6.0.2"
1241
+ "@types/better-sqlite3": "<%= versions["@types/better-sqlite3"] %>",
1242
+ "dotenv-cli": "<%= versions["dotenv-cli"] %>",
1243
+ "tsx": "<%= versions.tsx %>",
1244
+ "typescript": "<%= versions.typescript %>"
1241
1245
  }
1242
1246
  }`
1243
1247
  };
@@ -1257,15 +1261,15 @@ var package_json_postgres_default = {
1257
1261
  "make": "tsx scripts/new-migration.ts"
1258
1262
  },
1259
1263
  "dependencies": {
1260
- "kysely": "^0.28.2",
1261
- "pg": "^8.14.1"
1264
+ "kysely": "<%= versions.kysely %>",
1265
+ "pg": "<%= versions.pg %>"
1262
1266
  },
1263
1267
  "devDependencies": {
1264
1268
  "@<%= projectName %>/typescript-config": "workspace:*",
1265
- "@types/pg": "^8.11.13",
1266
- "dotenv-cli": "^11.0.0",
1267
- "tsx": "^4.19.2",
1268
- "typescript": "6.0.2"
1269
+ "@types/pg": "<%= versions["@types/pg"] %>",
1270
+ "dotenv-cli": "<%= versions["dotenv-cli"] %>",
1271
+ "tsx": "<%= versions.tsx %>",
1272
+ "typescript": "<%= versions.typescript %>"
1269
1273
  }
1270
1274
  }`
1271
1275
  };
@@ -1338,12 +1342,12 @@ var package_json_default5 = {
1338
1342
  },
1339
1343
  "devDependencies": {
1340
1344
  "@<%= projectName %>/typescript-config": "workspace:*",
1341
- "@tailwindcss/postcss": "^4.0.0",
1342
- "tailwindcss": "^4.0.0",
1343
- "@types/node": "^22.15.3",
1344
- "@types/react": "19.2.14",
1345
- "@types/react-dom": "19.2.3",
1346
- "typescript": "6.0.2"
1345
+ "@tailwindcss/postcss": "<%= versions["@tailwindcss/postcss"] %>",
1346
+ "tailwindcss": "<%= versions.tailwindcss %>",
1347
+ "@types/node": "<%= versions["@types/node"] %>",
1348
+ "@types/react": "<%= versions["@types/react"] %>",
1349
+ "@types/react-dom": "<%= versions["@types/react-dom"] %>",
1350
+ "typescript": "<%= versions.typescript %>"
1347
1351
  },
1348
1352
  "peerDependencies": {
1349
1353
  "next": ">=15.0.0",
@@ -1351,8 +1355,8 @@ var package_json_default5 = {
1351
1355
  "react-dom": ">=19.0.0"
1352
1356
  },
1353
1357
  "dependencies": {
1354
- "clsx": "^2.1.1",
1355
- "tailwind-merge": "^3.3.0"
1358
+ "clsx": "<%= versions.clsx %>",
1359
+ "tailwind-merge": "<%= versions["tailwind-merge"] %>"
1356
1360
  }
1357
1361
  }`
1358
1362
  };
@@ -1583,6 +1587,87 @@ var ui = {
1583
1587
  };
1584
1588
  var ui_default = ui;
1585
1589
 
1590
+ // src/templates/versions.ts
1591
+ var versions = {
1592
+ "@base-ui/react": "^1.6.0",
1593
+ "@eslint/eslintrc": "^3.2.0",
1594
+ "@eslint/js": "^9.39.1",
1595
+ "@nestjs/cli": "^11.0.0",
1596
+ "@nestjs/common": "^11.0.1",
1597
+ "@nestjs/core": "^11.0.1",
1598
+ "@nestjs/platform-express": "^11.0.1",
1599
+ "@nestjs/schematics": "^11.0.0",
1600
+ "@nestjs/serve-static": "^5.0.0",
1601
+ "@nestjs/testing": "^11.0.1",
1602
+ "@next/eslint-plugin-next": "^16.2.10",
1603
+ "@shadcn/react": "^0.2.1",
1604
+ "@swc/core": "^1.10.0",
1605
+ "@tailwindcss/postcss": "^4.2.1",
1606
+ "@tanstack/react-form": "^1.28.5",
1607
+ "@tanstack/react-query": "^5.90.21",
1608
+ "@thallesp/nestjs-better-auth": "^2.5.1",
1609
+ "@types/better-sqlite3": "^7.6.13",
1610
+ "@types/express": "^5.0.0",
1611
+ "@types/jest": "^30.0.0",
1612
+ "@types/node": "^22.15.3",
1613
+ "@types/pg": "^8.11.13",
1614
+ "@types/react": "19.2.14",
1615
+ "@types/react-dom": "19.2.3",
1616
+ "@types/supertest": "^6.0.2",
1617
+ "@vitest/coverage-v8": "^3.0.0",
1618
+ "auth": "^1.5.5",
1619
+ "better-auth": "^1.2.8",
1620
+ "better-sqlite3": "^12.11.1",
1621
+ "class-variance-authority": "^0.7.1",
1622
+ "clsx": "^2.1.1",
1623
+ "cmdk": "^1.1.1",
1624
+ "date-fns": "^4.2.1",
1625
+ "dotenv": "^17.3.1",
1626
+ "dotenv-cli": "^11.0.0",
1627
+ "embla-carousel-react": "^8.6.0",
1628
+ "eslint": "^9.39.1",
1629
+ "eslint-config-prettier": "^10.1.1",
1630
+ "eslint-plugin-only-warn": "^1.1.0",
1631
+ "eslint-plugin-react": "^7.37.5",
1632
+ "eslint-plugin-react-hooks": "^5.2.0",
1633
+ "eslint-plugin-turbo": "^2.7.1",
1634
+ "globals": "^16.5.0",
1635
+ "input-otp": "^1.4.2",
1636
+ "jest": "^30.0.0",
1637
+ "kysely": "^0.28.2",
1638
+ "lucide-react": "^1.16.0",
1639
+ "next": "16.2.10",
1640
+ "next-themes": "^0.4.6",
1641
+ "oxfmt": "^0.59.0",
1642
+ "oxlint": "^1.74.0",
1643
+ "pg": "^8.14.1",
1644
+ "prettier": "^3.7.4",
1645
+ "react": "^19.2.4",
1646
+ "react-day-picker": "^10.0.1",
1647
+ "react-dom": "^19.2.4",
1648
+ "react-resizable-panels": "^4.11.1",
1649
+ "recharts": "^3.8.0",
1650
+ "reflect-metadata": "^0.2.2",
1651
+ "rxjs": "^7.8.1",
1652
+ "shadcn": "^4.7.0",
1653
+ "sonner": "^2.0.7",
1654
+ "source-map-support": "^0.5.21",
1655
+ "supertest": "^7.0.0",
1656
+ "tailwind-merge": "^3.6.0",
1657
+ "tailwindcss": "^4.2.1",
1658
+ "ts-jest": "^29.2.5",
1659
+ "ts-loader": "^9.5.2",
1660
+ "ts-node": "^10.9.2",
1661
+ "tsconfig-paths": "^4.2.0",
1662
+ "tsx": "^4.19.4",
1663
+ "turbo": "^2.8.16",
1664
+ "tw-animate-css": "^1.4.0",
1665
+ "typescript": "6.0.2",
1666
+ "typescript-eslint": "^8.50.0",
1667
+ "unplugin-swc": "^1.5.9",
1668
+ "vitest": "^3.0.0"
1669
+ };
1670
+
1586
1671
  // src/templates/shadcn-ui/templates/components-json.ts
1587
1672
  var components_json_default = {
1588
1673
  filename: "packages/ui/components.json",
@@ -1657,22 +1742,23 @@ var package_json_default6 = {
1657
1742
  },
1658
1743
  "scripts": {},
1659
1744
  "dependencies": {
1660
- "@base-ui/react": "^1.6.0",
1661
- "shadcn": "^4.7.0",
1662
- "class-variance-authority": "^0.7.1",
1663
- "clsx": "^2.1.1",
1664
- "cmdk": "^1.1.1",
1665
- "date-fns": "^4.2.1",
1666
- "embla-carousel-react": "^8.6.0",
1667
- "input-otp": "^1.4.2",
1668
- "lucide-react": "^1.16.0",
1669
- "next-themes": "^0.4.6",
1670
- "react-day-picker": "^10.0.1",
1671
- "react-resizable-panels": "^4.11.1",
1672
- "recharts": "^3.8.0",
1673
- "sonner": "^2.0.7",
1674
- "tailwind-merge": "^3.6.0",
1675
- "tw-animate-css": "^1.4.0"
1745
+ "@base-ui/react": "<%= versions["@base-ui/react"] %>",
1746
+ "@shadcn/react": "<%= versions["@shadcn/react"] %>",
1747
+ "shadcn": "<%= versions.shadcn %>",
1748
+ "class-variance-authority": "<%= versions["class-variance-authority"] %>",
1749
+ "clsx": "<%= versions.clsx %>",
1750
+ "cmdk": "<%= versions.cmdk %>",
1751
+ "date-fns": "<%= versions["date-fns"] %>",
1752
+ "embla-carousel-react": "<%= versions["embla-carousel-react"] %>",
1753
+ "input-otp": "<%= versions["input-otp"] %>",
1754
+ "lucide-react": "<%= versions["lucide-react"] %>",
1755
+ "next-themes": "<%= versions["next-themes"] %>",
1756
+ "react-day-picker": "<%= versions["react-day-picker"] %>",
1757
+ "react-resizable-panels": "<%= versions["react-resizable-panels"] %>",
1758
+ "recharts": "<%= versions.recharts %>",
1759
+ "sonner": "<%= versions.sonner %>",
1760
+ "tailwind-merge": "<%= versions["tailwind-merge"] %>",
1761
+ "tw-animate-css": "<%= versions["tw-animate-css"] %>"
1676
1762
  },
1677
1763
  "peerDependencies": {
1678
1764
  "next": ">=15.0.0",
@@ -1681,12 +1767,12 @@ var package_json_default6 = {
1681
1767
  },
1682
1768
  "devDependencies": {
1683
1769
  "@<%= projectName %>/typescript-config": "workspace:*",
1684
- "@tailwindcss/postcss": "^4.0.8",
1685
- "@types/node": "^22.0.0",
1686
- "@types/react": "19.2.14",
1687
- "@types/react-dom": "19.2.3",
1688
- "tailwindcss": "^4.0.8",
1689
- "typescript": "6.0.2"
1770
+ "@tailwindcss/postcss": "<%= versions["@tailwindcss/postcss"] %>",
1771
+ "@types/node": "<%= versions["@types/node"] %>",
1772
+ "@types/react": "<%= versions["@types/react"] %>",
1773
+ "@types/react-dom": "<%= versions["@types/react-dom"] %>",
1774
+ "tailwindcss": "<%= versions.tailwindcss %>",
1775
+ "typescript": "<%= versions.typescript %>"
1690
1776
  }
1691
1777
  }`
1692
1778
  };
@@ -2013,6 +2099,7 @@ export default function RootLayout({
2013
2099
 
2014
2100
  // src/templates/shadcn-ui/templates/page.ts
2015
2101
  var page_default2 = {
2102
+ when: (s) => !s.todoExample,
2016
2103
  filename: "apps/web/app/page.tsx",
2017
2104
  template: `'use client';
2018
2105
 
@@ -9350,6 +9437,665 @@ export function ModeToggle() {
9350
9437
  `
9351
9438
  };
9352
9439
 
9440
+ // src/templates/shadcn-ui/templates/attachment.ts
9441
+ var attachment_default = {
9442
+ filename: "packages/ui/src/components/attachment.tsx",
9443
+ template: `import * as React from "react"
9444
+ import { mergeProps } from "@base-ui/react/merge-props"
9445
+ import { useRender } from "@base-ui/react/use-render"
9446
+ import { cva, type VariantProps } from "class-variance-authority"
9447
+
9448
+ import { cn } from "@<%= projectName %>/ui/lib/utils"
9449
+ import { Button } from "@<%= projectName %>/ui/components/button"
9450
+
9451
+ const attachmentVariants = cva(
9452
+ "group/attachment relative flex w-fit max-w-full min-w-0 shrink-0 flex-wrap rounded-xl border bg-card text-card-foreground transition-colors focus-within:ring-1 focus-within:ring-ring/50 has-[>a,>button]:hover:bg-muted/50 data-[state=error]:border-destructive/30 data-[state=idle]:border-dashed",
9453
+ {
9454
+ variants: {
9455
+ size: {
9456
+ default:
9457
+ "gap-2 text-sm has-data-[slot=attachment-content]:px-2.5 has-data-[slot=attachment-content]:py-2 has-data-[slot=attachment-media]:p-2",
9458
+ sm: "gap-2.5 text-xs has-data-[slot=attachment-content]:px-2 has-data-[slot=attachment-content]:py-1.5 has-data-[slot=attachment-media]:p-1.5",
9459
+ xs: "gap-1.5 rounded-lg text-xs has-data-[slot=attachment-content]:px-1.5 has-data-[slot=attachment-content]:py-1 has-data-[slot=attachment-media]:p-1",
9460
+ },
9461
+ orientation: {
9462
+ horizontal: "min-w-40 items-center",
9463
+ vertical: "w-24 flex-col has-data-[slot=attachment-content]:w-30",
9464
+ },
9465
+ },
9466
+ }
9467
+ )
9468
+
9469
+ function Attachment({
9470
+ className,
9471
+ state = "done",
9472
+ size = "default",
9473
+ orientation = "horizontal",
9474
+ ...props
9475
+ }: React.ComponentProps<"div"> &
9476
+ VariantProps<typeof attachmentVariants> & {
9477
+ state?: "idle" | "uploading" | "processing" | "error" | "done"
9478
+ }) {
9479
+ return (
9480
+ <div
9481
+ data-slot="attachment"
9482
+ data-state={state}
9483
+ data-size={size}
9484
+ data-orientation={orientation}
9485
+ className={cn(attachmentVariants({ size, orientation }), className)}
9486
+ {...props}
9487
+ />
9488
+ )
9489
+ }
9490
+
9491
+ const attachmentMediaVariants = cva(
9492
+ "relative flex aspect-square w-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted text-foreground group-data-[orientation=vertical]/attachment:w-full group-data-[size=sm]/attachment:w-8 group-data-[size=xs]/attachment:w-7 group-data-[size=xs]/attachment:rounded-md group-data-[state=error]/attachment:bg-destructive/10 group-data-[state=error]/attachment:text-destructive group-data-[orientation=vertical]/attachment:*:data-[slot=spinner]:size-6! [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 group-data-[orientation=vertical]/attachment:[&_svg:not([class*='size-'])]:size-6 group-data-[size=xs]/attachment:[&_svg:not([class*='size-'])]:size-3.5",
9493
+ {
9494
+ variants: {
9495
+ variant: {
9496
+ icon: "",
9497
+ image:
9498
+ "opacity-60 group-data-[state=done]/attachment:opacity-100 group-data-[state=idle]/attachment:opacity-100 *:[img]:aspect-square *:[img]:w-full *:[img]:object-cover",
9499
+ },
9500
+ },
9501
+ defaultVariants: {
9502
+ variant: "icon",
9503
+ },
9504
+ }
9505
+ )
9506
+
9507
+ function AttachmentMedia({
9508
+ className,
9509
+ variant = "icon",
9510
+ ...props
9511
+ }: React.ComponentProps<"div"> & VariantProps<typeof attachmentMediaVariants>) {
9512
+ return (
9513
+ <div
9514
+ data-slot="attachment-media"
9515
+ data-variant={variant}
9516
+ className={cn(attachmentMediaVariants({ variant }), className)}
9517
+ {...props}
9518
+ />
9519
+ )
9520
+ }
9521
+
9522
+ function AttachmentContent({
9523
+ className,
9524
+ ...props
9525
+ }: React.ComponentProps<"div">) {
9526
+ return (
9527
+ <div
9528
+ data-slot="attachment-content"
9529
+ className={cn(
9530
+ "max-w-full min-w-0 flex-1 leading-tight group-data-[orientation=vertical]/attachment:px-1",
9531
+ className
9532
+ )}
9533
+ {...props}
9534
+ />
9535
+ )
9536
+ }
9537
+
9538
+ function AttachmentTitle({
9539
+ className,
9540
+ ...props
9541
+ }: React.ComponentProps<"span">) {
9542
+ return (
9543
+ <span
9544
+ data-slot="attachment-title"
9545
+ className={cn(
9546
+ "block max-w-full min-w-0 truncate font-medium group-data-[state=processing]/attachment:shimmer group-data-[state=uploading]/attachment:shimmer",
9547
+ className
9548
+ )}
9549
+ {...props}
9550
+ />
9551
+ )
9552
+ }
9553
+
9554
+ function AttachmentDescription({
9555
+ className,
9556
+ ...props
9557
+ }: React.ComponentProps<"span">) {
9558
+ return (
9559
+ <span
9560
+ data-slot="attachment-description"
9561
+ className={cn(
9562
+ "mt-0.5 block min-w-0 truncate text-xs text-muted-foreground group-data-[state=error]/attachment:text-destructive/80",
9563
+ "max-w-full",
9564
+ className
9565
+ )}
9566
+ {...props}
9567
+ />
9568
+ )
9569
+ }
9570
+
9571
+ function AttachmentActions({
9572
+ className,
9573
+ ...props
9574
+ }: React.ComponentProps<"div">) {
9575
+ return (
9576
+ <div
9577
+ data-slot="attachment-actions"
9578
+ className={cn(
9579
+ "relative z-20 flex shrink-0 items-center group-data-[orientation=vertical]/attachment:absolute group-data-[orientation=vertical]/attachment:top-3 group-data-[orientation=vertical]/attachment:right-3 group-data-[orientation=vertical]/attachment:gap-1",
9580
+ className
9581
+ )}
9582
+ {...props}
9583
+ />
9584
+ )
9585
+ }
9586
+
9587
+ function AttachmentAction({
9588
+ className,
9589
+ variant,
9590
+ size = "icon-xs",
9591
+ ...props
9592
+ }: React.ComponentProps<typeof Button>) {
9593
+ return (
9594
+ <Button
9595
+ data-slot="attachment-action"
9596
+ variant={variant ?? "ghost"}
9597
+ size={size}
9598
+ className={cn(className)}
9599
+ {...props}
9600
+ />
9601
+ )
9602
+ }
9603
+
9604
+ function AttachmentTrigger({
9605
+ className,
9606
+ render,
9607
+ type,
9608
+ ...props
9609
+ }: useRender.ComponentProps<"button">) {
9610
+ return useRender({
9611
+ defaultTagName: "button",
9612
+ props: mergeProps<"button">(
9613
+ {
9614
+ type: render ? type : (type ?? "button"),
9615
+ className: cn("absolute inset-0 z-10 outline-none", className),
9616
+ },
9617
+ props
9618
+ ),
9619
+ render,
9620
+ state: {
9621
+ slot: "attachment-trigger",
9622
+ },
9623
+ })
9624
+ }
9625
+
9626
+ function AttachmentGroup({ className, ...props }: React.ComponentProps<"div">) {
9627
+ return (
9628
+ <div
9629
+ data-slot="attachment-group"
9630
+ className={cn(
9631
+ "flex min-w-0 scroll-fade-x snap-x snap-mandatory scroll-px-1 scrollbar-none gap-3 overflow-x-auto overscroll-x-contain py-1 *:data-[slot=attachment]:flex-none *:data-[slot=attachment]:snap-start",
9632
+ className
9633
+ )}
9634
+ {...props}
9635
+ />
9636
+ )
9637
+ }
9638
+
9639
+ export {
9640
+ Attachment,
9641
+ AttachmentGroup,
9642
+ AttachmentMedia,
9643
+ AttachmentContent,
9644
+ AttachmentTitle,
9645
+ AttachmentDescription,
9646
+ AttachmentActions,
9647
+ AttachmentAction,
9648
+ AttachmentTrigger,
9649
+ }
9650
+ `
9651
+ };
9652
+
9653
+ // src/templates/shadcn-ui/templates/bubble.ts
9654
+ var bubble_default = {
9655
+ filename: "packages/ui/src/components/bubble.tsx",
9656
+ template: `import * as React from "react"
9657
+ import { mergeProps } from "@base-ui/react/merge-props"
9658
+ import { useRender } from "@base-ui/react/use-render"
9659
+ import { cva, type VariantProps } from "class-variance-authority"
9660
+
9661
+ import { cn } from "@<%= projectName %>/ui/lib/utils"
9662
+
9663
+ function BubbleGroup({ className, ...props }: React.ComponentProps<"div">) {
9664
+ return (
9665
+ <div
9666
+ data-slot="bubble-group"
9667
+ className={cn("flex min-w-0 flex-col gap-2", className)}
9668
+ {...props}
9669
+ />
9670
+ )
9671
+ }
9672
+
9673
+ const bubbleVariants = cva(
9674
+ "group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full",
9675
+ {
9676
+ variants: {
9677
+ variant: {
9678
+ default:
9679
+ "*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80",
9680
+ secondary:
9681
+ "*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]",
9682
+ muted:
9683
+ "*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]",
9684
+ tinted:
9685
+ "*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.93_calc(c*0.4)_h)] *:data-[slot=bubble-content]:text-foreground dark:*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.3_calc(c*0.4)_h)] [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.88_calc(c*0.5)_h)] dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.35_calc(c*0.5)_h)]",
9686
+ outline:
9687
+ "*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-background [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30",
9688
+ ghost:
9689
+ "border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50",
9690
+ destructive:
9691
+ "*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30",
9692
+ },
9693
+ },
9694
+ defaultVariants: {
9695
+ variant: "default",
9696
+ },
9697
+ }
9698
+ )
9699
+
9700
+ function Bubble({
9701
+ variant = "default",
9702
+ align = "start",
9703
+ className,
9704
+ ...props
9705
+ }: React.ComponentProps<"div"> &
9706
+ VariantProps<typeof bubbleVariants> & {
9707
+ align?: "start" | "end"
9708
+ }) {
9709
+ return (
9710
+ <div
9711
+ data-slot="bubble"
9712
+ data-variant={variant}
9713
+ data-align={align}
9714
+ className={cn(bubbleVariants({ variant }), className)}
9715
+ {...props}
9716
+ />
9717
+ )
9718
+ }
9719
+
9720
+ function BubbleContent({
9721
+ className,
9722
+ render,
9723
+ ...props
9724
+ }: useRender.ComponentProps<"div">) {
9725
+ return useRender({
9726
+ defaultTagName: "div",
9727
+ props: mergeProps<"div">(
9728
+ {
9729
+ className: cn(
9730
+ "w-fit max-w-full min-w-0 overflow-hidden rounded-xl border border-transparent px-3 py-2 text-sm leading-relaxed wrap-break-word group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/50",
9731
+ className
9732
+ ),
9733
+ },
9734
+ props
9735
+ ),
9736
+ render,
9737
+ state: {
9738
+ slot: "bubble-content",
9739
+ },
9740
+ })
9741
+ }
9742
+
9743
+ const bubbleReactionsVariants = cva(
9744
+ "absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0",
9745
+ {
9746
+ variants: {
9747
+ side: {
9748
+ top: "top-0 -translate-y-3/4",
9749
+ bottom: "bottom-0 translate-y-3/4",
9750
+ },
9751
+ align: {
9752
+ start: "left-3",
9753
+ end: "right-3",
9754
+ },
9755
+ },
9756
+ defaultVariants: {
9757
+ side: "bottom",
9758
+ align: "end",
9759
+ },
9760
+ }
9761
+ )
9762
+
9763
+ function BubbleReactions({
9764
+ side = "bottom",
9765
+ align = "end",
9766
+ className,
9767
+ ...props
9768
+ }: React.ComponentProps<"div"> & {
9769
+ align?: "start" | "end"
9770
+ side?: "top" | "bottom"
9771
+ }) {
9772
+ return (
9773
+ <div
9774
+ data-slot="bubble-reactions"
9775
+ data-align={align}
9776
+ data-side={side}
9777
+ className={cn(bubbleReactionsVariants({ side, align }), className)}
9778
+ {...props}
9779
+ />
9780
+ )
9781
+ }
9782
+
9783
+ export { BubbleGroup, Bubble, BubbleContent, BubbleReactions }
9784
+ `
9785
+ };
9786
+
9787
+ // src/templates/shadcn-ui/templates/marker.ts
9788
+ var marker_default = {
9789
+ filename: "packages/ui/src/components/marker.tsx",
9790
+ template: `import * as React from "react"
9791
+ import { mergeProps } from "@base-ui/react/merge-props"
9792
+ import { useRender } from "@base-ui/react/use-render"
9793
+ import { cva, type VariantProps } from "class-variance-authority"
9794
+
9795
+ import { cn } from "@<%= projectName %>/ui/lib/utils"
9796
+
9797
+ const markerVariants = cva(
9798
+ "group/marker relative flex min-h-4 w-full items-center gap-2 text-left text-sm text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [a]:underline [a]:underline-offset-3 [a]:hover:text-foreground",
9799
+ {
9800
+ variants: {
9801
+ variant: {
9802
+ default: "",
9803
+ separator:
9804
+ "before:mr-1 before:h-px before:min-w-0 before:flex-1 before:bg-border after:ml-1 after:h-px after:min-w-0 after:flex-1 after:bg-border",
9805
+ border: "border-b border-border pb-2",
9806
+ },
9807
+ },
9808
+ }
9809
+ )
9810
+
9811
+ function Marker({
9812
+ className,
9813
+ variant = "default",
9814
+ render,
9815
+ ...props
9816
+ }: useRender.ComponentProps<"div"> & VariantProps<typeof markerVariants>) {
9817
+ return useRender({
9818
+ defaultTagName: "div",
9819
+ props: mergeProps<"div">(
9820
+ {
9821
+ className: cn(markerVariants({ variant, className })),
9822
+ },
9823
+ props
9824
+ ),
9825
+ render,
9826
+ state: {
9827
+ slot: "marker",
9828
+ variant,
9829
+ },
9830
+ })
9831
+ }
9832
+
9833
+ function MarkerIcon({ className, ...props }: React.ComponentProps<"span">) {
9834
+ return (
9835
+ <span
9836
+ data-slot="marker-icon"
9837
+ aria-hidden="true"
9838
+ className={cn(
9839
+ "size-4 shrink-0 [&_svg:not([class*='size-'])]:size-4",
9840
+ className
9841
+ )}
9842
+ {...props}
9843
+ />
9844
+ )
9845
+ }
9846
+
9847
+ function MarkerContent({ className, ...props }: React.ComponentProps<"span">) {
9848
+ return (
9849
+ <span
9850
+ data-slot="marker-content"
9851
+ className={cn(
9852
+ "min-w-0 wrap-break-word group-data-[variant=separator]/marker:flex-none group-data-[variant=separator]/marker:text-center *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
9853
+ className
9854
+ )}
9855
+ {...props}
9856
+ />
9857
+ )
9858
+ }
9859
+
9860
+ export { Marker, MarkerIcon, MarkerContent, markerVariants }
9861
+ `
9862
+ };
9863
+
9864
+ // src/templates/shadcn-ui/templates/message.ts
9865
+ var message_default = {
9866
+ filename: "packages/ui/src/components/message.tsx",
9867
+ template: `import * as React from "react"
9868
+
9869
+ import { cn } from "@<%= projectName %>/ui/lib/utils"
9870
+
9871
+ function MessageGroup({ className, ...props }: React.ComponentProps<"div">) {
9872
+ return (
9873
+ <div
9874
+ data-slot="message-group"
9875
+ className={cn("flex min-w-0 flex-col gap-2", className)}
9876
+ {...props}
9877
+ />
9878
+ )
9879
+ }
9880
+
9881
+ function Message({
9882
+ className,
9883
+ align = "start",
9884
+ ...props
9885
+ }: React.ComponentProps<"div"> & { align?: "start" | "end" }) {
9886
+ return (
9887
+ <div
9888
+ data-slot="message"
9889
+ data-align={align}
9890
+ className={cn(
9891
+ "group/message relative flex w-full min-w-0 gap-2 text-sm data-[align=end]:flex-row-reverse",
9892
+ className
9893
+ )}
9894
+ {...props}
9895
+ />
9896
+ )
9897
+ }
9898
+
9899
+ function MessageAvatar({ className, ...props }: React.ComponentProps<"div">) {
9900
+ return (
9901
+ <div
9902
+ data-slot="message-avatar"
9903
+ className={cn(
9904
+ "flex w-fit min-w-8 shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted group-has-data-[slot=message-footer]/message:-translate-y-8",
9905
+ className
9906
+ )}
9907
+ {...props}
9908
+ />
9909
+ )
9910
+ }
9911
+
9912
+ function MessageContent({ className, ...props }: React.ComponentProps<"div">) {
9913
+ return (
9914
+ <div
9915
+ data-slot="message-content"
9916
+ className={cn(
9917
+ "flex w-full min-w-0 flex-col gap-2.5 wrap-break-word group-data-[align=end]/message:*:data-slot:self-end",
9918
+ className
9919
+ )}
9920
+ {...props}
9921
+ />
9922
+ )
9923
+ }
9924
+
9925
+ function MessageHeader({ className, ...props }: React.ComponentProps<"div">) {
9926
+ return (
9927
+ <div
9928
+ data-slot="message-header"
9929
+ className={cn(
9930
+ "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0",
9931
+ className
9932
+ )}
9933
+ {...props}
9934
+ />
9935
+ )
9936
+ }
9937
+
9938
+ function MessageFooter({ className, ...props }: React.ComponentProps<"div">) {
9939
+ return (
9940
+ <div
9941
+ data-slot="message-footer"
9942
+ className={cn(
9943
+ "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0 group-data-[align=end]/message:justify-end",
9944
+ className
9945
+ )}
9946
+ {...props}
9947
+ />
9948
+ )
9949
+ }
9950
+
9951
+ export {
9952
+ MessageGroup,
9953
+ Message,
9954
+ MessageAvatar,
9955
+ MessageContent,
9956
+ MessageFooter,
9957
+ MessageHeader,
9958
+ }
9959
+ `
9960
+ };
9961
+
9962
+ // src/templates/shadcn-ui/templates/message-scroller.ts
9963
+ var message_scroller_default = {
9964
+ filename: "packages/ui/src/components/message-scroller.tsx",
9965
+ template: `"use client"
9966
+
9967
+ import * as React from "react"
9968
+ import {
9969
+ MessageScroller as MessageScrollerPrimitive,
9970
+ useMessageScroller,
9971
+ useMessageScrollerScrollable,
9972
+ useMessageScrollerVisibility,
9973
+ } from "@shadcn/react/message-scroller"
9974
+
9975
+ import { cn } from "@<%= projectName %>/ui/lib/utils"
9976
+ import { Button } from "@<%= projectName %>/ui/components/button"
9977
+ import { ArrowDownIcon } from "lucide-react"
9978
+
9979
+ function MessageScrollerProvider(
9980
+ props: React.ComponentProps<typeof MessageScrollerPrimitive.Provider>
9981
+ ) {
9982
+ return <MessageScrollerPrimitive.Provider {...props} />
9983
+ }
9984
+
9985
+ function MessageScroller({
9986
+ className,
9987
+ ...props
9988
+ }: React.ComponentProps<typeof MessageScrollerPrimitive.Root>) {
9989
+ return (
9990
+ <MessageScrollerPrimitive.Root
9991
+ data-slot="message-scroller"
9992
+ className={cn(
9993
+ "group/message-scroller relative flex size-full min-h-0 flex-col overflow-hidden",
9994
+ className
9995
+ )}
9996
+ {...props}
9997
+ />
9998
+ )
9999
+ }
10000
+
10001
+ function MessageScrollerViewport({
10002
+ className,
10003
+ ...props
10004
+ }: React.ComponentProps<typeof MessageScrollerPrimitive.Viewport>) {
10005
+ return (
10006
+ <MessageScrollerPrimitive.Viewport
10007
+ data-slot="message-scroller-viewport"
10008
+ className={cn(
10009
+ "size-full min-h-0 min-w-0 scroll-fade-b scrollbar-thin scrollbar-gutter-stable overflow-y-auto overscroll-contain contain-content data-autoscrolling:scrollbar-thumb-transparent data-autoscrolling:scrollbar-track-transparent",
10010
+ className
10011
+ )}
10012
+ {...props}
10013
+ />
10014
+ )
10015
+ }
10016
+
10017
+ function MessageScrollerContent({
10018
+ className,
10019
+ ...props
10020
+ }: React.ComponentProps<typeof MessageScrollerPrimitive.Content>) {
10021
+ return (
10022
+ <MessageScrollerPrimitive.Content
10023
+ data-slot="message-scroller-content"
10024
+ className={cn("flex h-max min-h-full flex-col gap-6", className)}
10025
+ {...props}
10026
+ />
10027
+ )
10028
+ }
10029
+
10030
+ function MessageScrollerItem({
10031
+ className,
10032
+ scrollAnchor = false,
10033
+ ...props
10034
+ }: React.ComponentProps<typeof MessageScrollerPrimitive.Item>) {
10035
+ return (
10036
+ <MessageScrollerPrimitive.Item
10037
+ data-slot="message-scroller-item"
10038
+ scrollAnchor={scrollAnchor}
10039
+ className={cn(
10040
+ "min-w-0 shrink-0 [contain-intrinsic-size:auto_10rem] [content-visibility:auto]",
10041
+ className
10042
+ )}
10043
+ {...props}
10044
+ />
10045
+ )
10046
+ }
10047
+
10048
+ function MessageScrollerButton({
10049
+ direction = "end",
10050
+ className,
10051
+ children,
10052
+ render,
10053
+ variant = "secondary",
10054
+ size = "icon-sm",
10055
+ ...props
10056
+ }: React.ComponentProps<typeof MessageScrollerPrimitive.Button> &
10057
+ Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
10058
+ return (
10059
+ <MessageScrollerPrimitive.Button
10060
+ data-slot="message-scroller-button"
10061
+ data-direction={direction}
10062
+ data-variant={variant}
10063
+ data-size={size}
10064
+ direction={direction}
10065
+ className={cn(
10066
+ "absolute inset-s-1/2 -translate-x-1/2 border-border bg-background text-foreground transition-[translate,scale,opacity] duration-200 hover:bg-muted hover:text-foreground data-[active=false]:pointer-events-none data-[active=false]:scale-95 data-[active=false]:opacity-0 data-[active=false]:duration-400 data-[active=false]:ease-[cubic-bezier(0.7,0,0.84,0)] data-[active=true]:translate-y-0 data-[active=true]:scale-100 data-[active=true]:opacity-100 data-[active=true]:ease-[cubic-bezier(0.23,1,0.32,1)] data-[direction=end]:bottom-4 data-[direction=end]:data-[active=false]:translate-y-full data-[direction=start]:top-4 data-[direction=start]:data-[active=false]:-translate-y-full rtl:translate-x-1/2 data-[direction=start]:[&_svg]:rotate-180",
10067
+ className
10068
+ )}
10069
+ render={render ?? <Button variant={variant} size={size} />}
10070
+ {...props}
10071
+ >
10072
+ {children ?? (
10073
+ <>
10074
+ <ArrowDownIcon
10075
+ />
10076
+ <span className="sr-only">
10077
+ {direction === "end" ? "Scroll to end" : "Scroll to start"}
10078
+ </span>
10079
+ </>
10080
+ )}
10081
+ </MessageScrollerPrimitive.Button>
10082
+ )
10083
+ }
10084
+
10085
+ export {
10086
+ MessageScrollerProvider,
10087
+ MessageScroller,
10088
+ MessageScrollerViewport,
10089
+ MessageScrollerContent,
10090
+ MessageScrollerItem,
10091
+ MessageScrollerButton,
10092
+ useMessageScroller,
10093
+ useMessageScrollerScrollable,
10094
+ useMessageScrollerVisibility,
10095
+ }
10096
+ `
10097
+ };
10098
+
9353
10099
  // src/templates/shadcn-ui/index.ts
9354
10100
  var shadcnUi = {
9355
10101
  templates: [
@@ -9421,12 +10167,17 @@ var shadcnUi = {
9421
10167
  toggle_default,
9422
10168
  tooltip_default,
9423
10169
  mode_toggle_default,
10170
+ attachment_default,
10171
+ bubble_default,
10172
+ marker_default,
10173
+ message_default,
10174
+ message_scroller_default,
9424
10175
  components_json_default,
9425
10176
  web_components_json_default
9426
10177
  ],
9427
10178
  packages: [
9428
- { package: "next-themes", module: "apps/web", version: "^0.4.6" },
9429
- { package: "sonner", module: "apps/web", version: "^2.0.7" }
10179
+ { package: "next-themes", module: "apps/web", version: versions["next-themes"] },
10180
+ { package: "sonner", module: "apps/web", version: versions.sonner }
9430
10181
  ]
9431
10182
  };
9432
10183
  var shadcn_ui_default = shadcnUi;
@@ -9445,17 +10196,17 @@ var package_json_default7 = {
9445
10196
  "./react-internal": "./react-internal.js"
9446
10197
  },
9447
10198
  "devDependencies": {
9448
- "@eslint/js": "^9.39.1",
9449
- "@next/eslint-plugin-next": "^16.2.10",
9450
- "eslint": "^9.39.1",
9451
- "eslint-config-prettier": "^10.1.1",
9452
- "eslint-plugin-only-warn": "^1.1.0",
9453
- "eslint-plugin-react": "^7.37.5",
9454
- "eslint-plugin-react-hooks": "^5.2.0",
9455
- "eslint-plugin-turbo": "^2.7.1",
9456
- "globals": "^16.5.0",
9457
- "typescript": "^5.9.2",
9458
- "typescript-eslint": "^8.50.0"
10199
+ "@eslint/js": "<%= versions["@eslint/js"] %>",
10200
+ "@next/eslint-plugin-next": "<%= versions["@next/eslint-plugin-next"] %>",
10201
+ "eslint": "<%= versions.eslint %>",
10202
+ "eslint-config-prettier": "<%= versions["eslint-config-prettier"] %>",
10203
+ "eslint-plugin-only-warn": "<%= versions["eslint-plugin-only-warn"] %>",
10204
+ "eslint-plugin-react": "<%= versions["eslint-plugin-react"] %>",
10205
+ "eslint-plugin-react-hooks": "<%= versions["eslint-plugin-react-hooks"] %>",
10206
+ "eslint-plugin-turbo": "<%= versions["eslint-plugin-turbo"] %>",
10207
+ "globals": "<%= versions.globals %>",
10208
+ "typescript": "<%= versions.typescript %>",
10209
+ "typescript-eslint": "<%= versions["typescript-eslint"] %>"
9459
10210
  }
9460
10211
  }`
9461
10212
  };
@@ -9661,25 +10412,34 @@ var eslint_config_default3 = {
9661
10412
  export default config;`
9662
10413
  };
9663
10414
 
10415
+ // src/templates/root/templates/prettierrc.ts
10416
+ var prettierrc_default = {
10417
+ filename: ".prettierrc",
10418
+ template: `{
10419
+ "singleQuote": true,
10420
+ "trailingComma": "all"
10421
+ }`
10422
+ };
10423
+
9664
10424
  // src/templates/eslint-config/index.ts
9665
10425
  var web2 = "apps/web";
9666
10426
  var api2 = "apps/api";
9667
10427
  var ui2 = "packages/ui";
9668
10428
  var root2 = "";
9669
10429
  var eslintConfig = {
9670
- templates: [package_json_default7, base_default, next_default, react_internal_default, eslint_config_default, eslint_config_default2, eslint_config_default3],
10430
+ templates: [package_json_default7, base_default, next_default, react_internal_default, eslint_config_default, eslint_config_default2, eslint_config_default3, prettierrc_default],
9671
10431
  packages: [
9672
- { package: "eslint", module: web2, version: "^9.39.1", dev: true },
10432
+ { package: "eslint", module: web2, version: versions.eslint, dev: true },
9673
10433
  { package: "@<%= projectName %>/eslint-config", module: web2, version: "workspace:*", dev: true },
9674
- { package: "@eslint/eslintrc", module: api2, version: "^3.2.0", dev: true },
9675
- { package: "@eslint/js", module: api2, version: "^9.18.0", dev: true },
9676
- { package: "eslint", module: api2, version: "^9.18.0", dev: true },
9677
- { package: "eslint-config-prettier", module: api2, version: "^10.0.1", dev: true },
9678
- { package: "globals", module: api2, version: "^16.0.0", dev: true },
9679
- { package: "typescript-eslint", module: api2, version: "^8.20.0", dev: true },
9680
- { package: "eslint", module: ui2, version: "^9.39.1", dev: true },
10434
+ { package: "@eslint/eslintrc", module: api2, version: versions["@eslint/eslintrc"], dev: true },
10435
+ { package: "@eslint/js", module: api2, version: versions["@eslint/js"], dev: true },
10436
+ { package: "eslint", module: api2, version: versions.eslint, dev: true },
10437
+ { package: "eslint-config-prettier", module: api2, version: versions["eslint-config-prettier"], dev: true },
10438
+ { package: "globals", module: api2, version: versions.globals, dev: true },
10439
+ { package: "typescript-eslint", module: api2, version: versions["typescript-eslint"], dev: true },
10440
+ { package: "eslint", module: ui2, version: versions.eslint, dev: true },
9681
10441
  { package: "@<%= projectName %>/eslint-config", module: ui2, version: "workspace:*", dev: true },
9682
- { package: "prettier", module: root2, version: "^3.7.4", dev: true }
10442
+ { package: "prettier", module: root2, version: versions.prettier, dev: true }
9683
10443
  ],
9684
10444
  scripts: [
9685
10445
  { module: web2, name: "lint", script: "eslint --fix && next typegen && tsc --noEmit" },
@@ -9722,10 +10482,10 @@ var root3 = "";
9722
10482
  var oxc = {
9723
10483
  templates: [oxlintrc_default, oxfmtrc_default],
9724
10484
  packages: [
9725
- { package: "oxlint", module: web3, version: "^1.74.0", dev: true },
9726
- { package: "oxlint", module: api3, version: "^1.74.0", dev: true },
9727
- { package: "oxlint", module: ui3, version: "^1.74.0", dev: true },
9728
- { package: "oxfmt", module: root3, version: "^0.59.0", dev: true }
10485
+ { package: "oxlint", module: web3, version: versions.oxlint, dev: true },
10486
+ { package: "oxlint", module: api3, version: versions.oxlint, dev: true },
10487
+ { package: "oxlint", module: ui3, version: versions.oxlint, dev: true },
10488
+ { package: "oxfmt", module: root3, version: versions.oxfmt, dev: true }
9729
10489
  ],
9730
10490
  scripts: [
9731
10491
  { module: web3, name: "lint", script: "oxlint --fix && next typegen && tsc --noEmit" },
@@ -9898,11 +10658,11 @@ module.exports = {
9898
10658
  var testingJest = {
9899
10659
  templates: [jest_config_default, jest_e2e_config_default, e2e_spec_default, nestjs_better_auth_mock_default],
9900
10660
  packages: [
9901
- { package: "jest", module: "apps/api", version: "^30.0.0", dev: true },
9902
- { package: "ts-jest", module: "apps/api", version: "^29.2.5", dev: true },
9903
- { package: "@types/jest", module: "apps/api", version: "^30.0.0", dev: true },
9904
- { package: "ts-loader", module: "apps/api", version: "^9.5.2", dev: true },
9905
- { package: "source-map-support", module: "apps/api", version: "^0.5.21", dev: true }
10661
+ { package: "jest", module: "apps/api", version: versions.jest, dev: true },
10662
+ { package: "ts-jest", module: "apps/api", version: versions["ts-jest"], dev: true },
10663
+ { package: "@types/jest", module: "apps/api", version: versions["@types/jest"], dev: true },
10664
+ { package: "ts-loader", module: "apps/api", version: versions["ts-loader"], dev: true },
10665
+ { package: "source-map-support", module: "apps/api", version: versions["source-map-support"], dev: true }
9906
10666
  ],
9907
10667
  scripts: [
9908
10668
  { module: "apps/api", name: "test", script: "jest" },
@@ -9984,10 +10744,10 @@ describe('AppController (e2e)', () => {
9984
10744
  var testingVitest = {
9985
10745
  templates: [vitest_config_default, vitest_config_e2e_default, e2e_spec_default2],
9986
10746
  packages: [
9987
- { package: "vitest", module: "apps/api", version: "^3.0.0", dev: true },
9988
- { package: "@vitest/coverage-v8", module: "apps/api", version: "^3.0.0", dev: true },
9989
- { package: "unplugin-swc", module: "apps/api", version: "^1.5.9", dev: true },
9990
- { package: "@swc/core", module: "apps/api", version: "^1.10.0", dev: true }
10747
+ { package: "vitest", module: "apps/api", version: versions.vitest, dev: true },
10748
+ { package: "@vitest/coverage-v8", module: "apps/api", version: versions["@vitest/coverage-v8"], dev: true },
10749
+ { package: "unplugin-swc", module: "apps/api", version: versions["unplugin-swc"], dev: true },
10750
+ { package: "@swc/core", module: "apps/api", version: versions["@swc/core"], dev: true }
9991
10751
  ],
9992
10752
  scripts: [
9993
10753
  { module: "apps/api", name: "test", script: "vitest run" },
@@ -10001,6 +10761,7 @@ var testing_vitest_default = testingVitest;
10001
10761
 
10002
10762
  // src/templates/deployment-standalone/templates/dockerfile.ts
10003
10763
  var dockerfile_default = {
10764
+ when: (s) => !s.nestDiOnly,
10004
10765
  filename: "Dockerfile",
10005
10766
  template: `FROM node:22-alpine AS base
10006
10767
  ENV PNPM_HOME="/pnpm"
@@ -10042,9 +10803,13 @@ CMD ["pnpm", "db:migrate"]`
10042
10803
 
10043
10804
  // src/templates/deployment-standalone/templates/docker-compose.ts
10044
10805
  var docker_compose_default = {
10806
+ when: (s) => !s.nestDiOnly,
10045
10807
  filename: "docker-compose.yml",
10046
10808
  template: `x-app-env: &app-env
10047
10809
  BETTER_AUTH_SECRET: \${BETTER_AUTH_SECRET}
10810
+ # Better Auth trusts this origin; without it every deployment falls back to
10811
+ # localhost:3000 and rejects requests from the real one.
10812
+ BETTER_AUTH_URL: \${BETTER_AUTH_URL:-http://localhost:3000}
10048
10813
  DATABASE_URL: postgresql://postgres:\${POSTGRES_PASSWORD:-postgres}@db:5432/postgres
10049
10814
 
10050
10815
  services:
@@ -10106,6 +10871,7 @@ volumes:
10106
10871
 
10107
10872
  // src/templates/deployment-standalone/templates/next-config.ts
10108
10873
  var next_config_default2 = {
10874
+ when: (s) => !s.nestDiOnly,
10109
10875
  filename: "apps/web/next.config.js",
10110
10876
  template: `import dotenv from 'dotenv';
10111
10877
  import { resolve } from 'path';
@@ -10193,27 +10959,27 @@ var api_package_json_default = {
10193
10959
  "start:prod": "node dist/main"
10194
10960
  },
10195
10961
  "dependencies": {
10196
- "@nestjs/common": "^11.0.1",
10197
- "@nestjs/core": "^11.0.1",
10198
- "@nestjs/platform-express": "^11.0.1",
10962
+ "@nestjs/common": "<%= versions["@nestjs/common"] %>",
10963
+ "@nestjs/core": "<%= versions["@nestjs/core"] %>",
10964
+ "@nestjs/platform-express": "<%= versions["@nestjs/platform-express"] %>",
10199
10965
  "@<%= projectName %>/auth": "workspace:*",
10200
10966
  "@<%= projectName %>/db": "workspace:*",
10201
- "@thallesp/nestjs-better-auth": "^2.5.1",
10202
- "dotenv": "^17.3.1",
10203
- "reflect-metadata": "^0.2.2",
10204
- "rxjs": "^7.8.1"
10967
+ "@thallesp/nestjs-better-auth": "<%= versions["@thallesp/nestjs-better-auth"] %>",
10968
+ "dotenv": "<%= versions.dotenv %>",
10969
+ "reflect-metadata": "<%= versions["reflect-metadata"] %>",
10970
+ "rxjs": "<%= versions.rxjs %>"
10205
10971
  },
10206
10972
  "devDependencies": {
10207
- "@nestjs/cli": "^11.0.0",
10208
- "@nestjs/schematics": "^11.0.0",
10209
- "@nestjs/testing": "^11.0.1",
10210
- "@types/express": "^5.0.0",
10211
- "@types/node": "^22.10.7",
10212
- "@types/supertest": "^6.0.2",
10213
- "supertest": "^7.0.0",
10214
- "ts-node": "^10.9.2",
10215
- "tsconfig-paths": "^4.2.0",
10216
- "typescript": "6.0.2"
10973
+ "@nestjs/cli": "<%= versions["@nestjs/cli"] %>",
10974
+ "@nestjs/schematics": "<%= versions["@nestjs/schematics"] %>",
10975
+ "@nestjs/testing": "<%= versions["@nestjs/testing"] %>",
10976
+ "@types/express": "<%= versions["@types/express"] %>",
10977
+ "@types/node": "<%= versions["@types/node"] %>",
10978
+ "@types/supertest": "<%= versions["@types/supertest"] %>",
10979
+ "supertest": "<%= versions.supertest %>",
10980
+ "ts-node": "<%= versions["ts-node"] %>",
10981
+ "tsconfig-paths": "<%= versions["tsconfig-paths"] %>",
10982
+ "typescript": "<%= versions.typescript %>"
10217
10983
  }
10218
10984
  }`
10219
10985
  };
@@ -10292,31 +11058,32 @@ var web_package_json_default = {
10292
11058
  "@<%= projectName %>/api": "workspace:*",
10293
11059
  "@<%= projectName %>/auth": "workspace:*",
10294
11060
  "@<%= projectName %>/ui": "workspace:*",
10295
- "@nestjs/core": "^11.0.1",
10296
- "@tailwindcss/postcss": "^4.2.1",
10297
- "dotenv": "^17.3.1",
10298
- "@tanstack/react-form": "^1.28.5",
10299
- "@tanstack/react-query": "^5.90.21",
10300
- "better-auth": "^1.2.8",
10301
- "next": "16.2.10",
10302
- "react": "^19.2.4",
10303
- "react-dom": "^19.2.4",
10304
- "reflect-metadata": "^0.2.2",
10305
- "tailwindcss": "^4.2.1"
11061
+ "@nestjs/core": "<%= versions["@nestjs/core"] %>",
11062
+ "@tailwindcss/postcss": "<%= versions["@tailwindcss/postcss"] %>",
11063
+ "dotenv": "<%= versions.dotenv %>",
11064
+ "@tanstack/react-form": "<%= versions["@tanstack/react-form"] %>",
11065
+ "@tanstack/react-query": "<%= versions["@tanstack/react-query"] %>",
11066
+ "better-auth": "<%= versions["better-auth"] %>",
11067
+ "next": "<%= versions.next %>",
11068
+ "react": "<%= versions.react %>",
11069
+ "react-dom": "<%= versions["react-dom"] %>",
11070
+ "reflect-metadata": "<%= versions["reflect-metadata"] %>",
11071
+ "tailwindcss": "<%= versions.tailwindcss %>"
10306
11072
  },
10307
11073
  "devDependencies": {
10308
11074
  "@<%= projectName %>/typescript-config": "workspace:*",
10309
- "@types/node": "^22.15.3",
10310
- "@types/react": "19.2.14",
10311
- "@types/react-dom": "19.2.3",
10312
- "tsx": "^4.19.4",
10313
- "typescript": "6.0.2"
11075
+ "@types/node": "<%= versions["@types/node"] %>",
11076
+ "@types/react": "<%= versions["@types/react"] %>",
11077
+ "@types/react-dom": "<%= versions["@types/react-dom"] %>",
11078
+ "tsx": "<%= versions.tsx %>",
11079
+ "typescript": "<%= versions.typescript %>"
10314
11080
  }
10315
11081
  }`
10316
11082
  };
10317
11083
 
10318
11084
  // src/templates/single-process-custom-server/templates/web-next-config.ts
10319
11085
  var web_next_config_default = {
11086
+ when: (s) => !s.nestDiOnly,
10320
11087
  filename: "apps/web/next.config.js",
10321
11088
  template: `import dotenv from 'dotenv';
10322
11089
  import { resolve } from 'path';
@@ -10452,28 +11219,28 @@ var api_package_json_default2 = {
10452
11219
  "start:prod": "node dist/main"
10453
11220
  },
10454
11221
  "dependencies": {
10455
- "@nestjs/common": "^11.0.1",
10456
- "@nestjs/core": "^11.0.1",
10457
- "@nestjs/platform-express": "^11.0.1",
10458
- "@nestjs/serve-static": "^5.0.0",
11222
+ "@nestjs/common": "<%= versions["@nestjs/common"] %>",
11223
+ "@nestjs/core": "<%= versions["@nestjs/core"] %>",
11224
+ "@nestjs/platform-express": "<%= versions["@nestjs/platform-express"] %>",
11225
+ "@nestjs/serve-static": "<%= versions["@nestjs/serve-static"] %>",
10459
11226
  "@<%= projectName %>/auth": "workspace:*",
10460
11227
  "@<%= projectName %>/db": "workspace:*",
10461
- "@thallesp/nestjs-better-auth": "^2.5.1",
10462
- "dotenv": "^17.3.1",
10463
- "reflect-metadata": "^0.2.2",
10464
- "rxjs": "^7.8.1"
11228
+ "@thallesp/nestjs-better-auth": "<%= versions["@thallesp/nestjs-better-auth"] %>",
11229
+ "dotenv": "<%= versions.dotenv %>",
11230
+ "reflect-metadata": "<%= versions["reflect-metadata"] %>",
11231
+ "rxjs": "<%= versions.rxjs %>"
10465
11232
  },
10466
11233
  "devDependencies": {
10467
- "@nestjs/cli": "^11.0.0",
10468
- "@nestjs/schematics": "^11.0.0",
10469
- "@nestjs/testing": "^11.0.1",
10470
- "@types/express": "^5.0.0",
10471
- "@types/node": "^22.10.7",
10472
- "@types/supertest": "^6.0.2",
10473
- "supertest": "^7.0.0",
10474
- "ts-node": "^10.9.2",
10475
- "tsconfig-paths": "^4.2.0",
10476
- "typescript": "6.0.2"
11234
+ "@nestjs/cli": "<%= versions["@nestjs/cli"] %>",
11235
+ "@nestjs/schematics": "<%= versions["@nestjs/schematics"] %>",
11236
+ "@nestjs/testing": "<%= versions["@nestjs/testing"] %>",
11237
+ "@types/express": "<%= versions["@types/express"] %>",
11238
+ "@types/node": "<%= versions["@types/node"] %>",
11239
+ "@types/supertest": "<%= versions["@types/supertest"] %>",
11240
+ "supertest": "<%= versions.supertest %>",
11241
+ "ts-node": "<%= versions["ts-node"] %>",
11242
+ "tsconfig-paths": "<%= versions["tsconfig-paths"] %>",
11243
+ "typescript": "<%= versions.typescript %>"
10477
11244
  }
10478
11245
  }`
10479
11246
  };
@@ -10535,23 +11302,23 @@ var api_package_json_default3 = {
10535
11302
  "build": "nest build"
10536
11303
  },
10537
11304
  "dependencies": {
10538
- "@nestjs/common": "^11.0.1",
10539
- "@nestjs/core": "^11.0.1",
11305
+ "@nestjs/common": "<%= versions["@nestjs/common"] %>",
11306
+ "@nestjs/core": "<%= versions["@nestjs/core"] %>",
10540
11307
  "@<%= projectName %>/auth": "workspace:*",
10541
11308
  "@<%= projectName %>/db": "workspace:*",
10542
- "@thallesp/nestjs-better-auth": "^2.5.1",
10543
- "dotenv": "^17.3.1",
10544
- "reflect-metadata": "^0.2.2",
10545
- "rxjs": "^7.8.1"
11309
+ "@thallesp/nestjs-better-auth": "<%= versions["@thallesp/nestjs-better-auth"] %>",
11310
+ "dotenv": "<%= versions.dotenv %>",
11311
+ "reflect-metadata": "<%= versions["reflect-metadata"] %>",
11312
+ "rxjs": "<%= versions.rxjs %>"
10546
11313
  },
10547
11314
  "devDependencies": {
10548
- "@nestjs/cli": "^11.0.0",
10549
- "@nestjs/schematics": "^11.0.0",
10550
- "@nestjs/testing": "^11.0.1",
10551
- "@types/node": "^22.10.7",
10552
- "ts-node": "^10.9.2",
10553
- "tsconfig-paths": "^4.2.0",
10554
- "typescript": "6.0.2"
11315
+ "@nestjs/cli": "<%= versions["@nestjs/cli"] %>",
11316
+ "@nestjs/schematics": "<%= versions["@nestjs/schematics"] %>",
11317
+ "@nestjs/testing": "<%= versions["@nestjs/testing"] %>",
11318
+ "@types/node": "<%= versions["@types/node"] %>",
11319
+ "ts-node": "<%= versions["ts-node"] %>",
11320
+ "tsconfig-paths": "<%= versions["tsconfig-paths"] %>",
11321
+ "typescript": "<%= versions.typescript %>"
10555
11322
  }
10556
11323
  }`
10557
11324
  };
@@ -10590,6 +11357,7 @@ var api_tsconfig_default = {
10590
11357
 
10591
11358
  // src/templates/nest-di-only/templates/api-index.ts
10592
11359
  var api_index_default = {
11360
+ when: (s) => !s.todoExample,
10593
11361
  filename: "apps/api/src/index.ts",
10594
11362
  template: `export { AppModule } from './app.module';
10595
11363
  export { AppService } from './app.service';`
@@ -10639,31 +11407,32 @@ var web_package_json_default2 = {
10639
11407
  "@<%= projectName %>/auth": "workspace:*",
10640
11408
  "@<%= projectName %>/db": "workspace:*",
10641
11409
  "@<%= projectName %>/ui": "workspace:*",
10642
- "@nestjs/common": "^11.0.1",
10643
- "@nestjs/core": "^11.0.1",
10644
- "reflect-metadata": "^0.2.2",
10645
- "@tailwindcss/postcss": "^4.2.1",
10646
- "dotenv": "^17.3.1",
10647
- "@tanstack/react-form": "^1.28.5",
10648
- "@tanstack/react-query": "^5.90.21",
10649
- "better-auth": "^1.2.8",
10650
- "next": "16.2.10",
10651
- "react": "^19.2.4",
10652
- "react-dom": "^19.2.4",
10653
- "tailwindcss": "^4.2.1"
11410
+ "@nestjs/common": "<%= versions["@nestjs/common"] %>",
11411
+ "@nestjs/core": "<%= versions["@nestjs/core"] %>",
11412
+ "reflect-metadata": "<%= versions["reflect-metadata"] %>",
11413
+ "@tailwindcss/postcss": "<%= versions["@tailwindcss/postcss"] %>",
11414
+ "dotenv": "<%= versions.dotenv %>",
11415
+ "@tanstack/react-form": "<%= versions["@tanstack/react-form"] %>",
11416
+ "@tanstack/react-query": "<%= versions["@tanstack/react-query"] %>",
11417
+ "better-auth": "<%= versions["better-auth"] %>",
11418
+ "next": "<%= versions.next %>",
11419
+ "react": "<%= versions.react %>",
11420
+ "react-dom": "<%= versions["react-dom"] %>",
11421
+ "tailwindcss": "<%= versions.tailwindcss %>"
10654
11422
  },
10655
11423
  "devDependencies": {
10656
11424
  "@<%= projectName %>/typescript-config": "workspace:*",
10657
- "@types/node": "^22.15.3",
10658
- "@types/react": "19.2.14",
10659
- "@types/react-dom": "19.2.3",
10660
- "typescript": "6.0.2"
11425
+ "@types/node": "<%= versions["@types/node"] %>",
11426
+ "@types/react": "<%= versions["@types/react"] %>",
11427
+ "@types/react-dom": "<%= versions["@types/react-dom"] %>",
11428
+ "typescript": "<%= versions.typescript %>"
10661
11429
  }
10662
11430
  }`
10663
11431
  };
10664
11432
 
10665
11433
  // src/templates/nest-di-only/templates/web-next-config.ts
10666
11434
  var web_next_config_default3 = {
11435
+ when: (s) => s.deployment !== "standalone",
10667
11436
  filename: "apps/web/next.config.js",
10668
11437
  template: `import dotenv from 'dotenv';
10669
11438
  import { resolve } from 'path';
@@ -10783,6 +11552,9 @@ var docker_compose_default2 = {
10783
11552
  filename: "docker-compose.yml",
10784
11553
  template: `x-app-env: &app-env
10785
11554
  BETTER_AUTH_SECRET: \${BETTER_AUTH_SECRET}
11555
+ # Better Auth trusts this origin; without it every deployment falls back to
11556
+ # localhost:3000 and rejects requests from the real one.
11557
+ BETTER_AUTH_URL: \${BETTER_AUTH_URL:-http://localhost:3000}
10786
11558
  DATABASE_URL: postgresql://postgres:\${POSTGRES_PASSWORD:-postgres}@db:5432/postgres
10787
11559
 
10788
11560
  services:
@@ -10920,6 +11692,7 @@ describe('AppController', () => {
10920
11692
 
10921
11693
  // src/templates/api-controllers/templates/app-module.ts
10922
11694
  var app_module_default2 = {
11695
+ when: (s) => !s.nestDiOnly && !s.todoExample,
10923
11696
  filename: "apps/api/src/app.module.ts",
10924
11697
  template: `<% if (deployment === 'spa') { %>import { join } from 'path';
10925
11698
  <% } %>import { Module } from '@nestjs/common';
@@ -10985,6 +11758,7 @@ var api_controllers_default = apiControllers;
10985
11758
 
10986
11759
  // src/templates/todo-example/templates/todos-module.ts
10987
11760
  var todos_module_default = {
11761
+ when: (s) => s.nestDiOnly,
10988
11762
  filename: "apps/api/src/todos/todos.module.ts",
10989
11763
  template: `import { Module } from '@nestjs/common';
10990
11764
  import { TodosService } from './todos.service';
@@ -11243,6 +12017,7 @@ export class TodosModule {}`
11243
12017
 
11244
12018
  // src/templates/todo-example/templates/app-module-controllers.ts
11245
12019
  var app_module_controllers_default = {
12020
+ when: (s) => !s.nestDiOnly && s.todoExample,
11246
12021
  filename: "apps/api/src/app.module.ts",
11247
12022
  template: `<% if (deployment === 'spa') { %>import { join } from 'path';
11248
12023
  <% } %>import { Module } from '@nestjs/common';
@@ -11274,6 +12049,7 @@ export class AppModule {}`
11274
12049
 
11275
12050
  // src/templates/todo-example/templates/app-module-di.ts
11276
12051
  var app_module_di_default = {
12052
+ when: (s) => s.nestDiOnly && s.todoExample,
11277
12053
  filename: "apps/api/src/app.module.ts",
11278
12054
  template: `import { Module } from '@nestjs/common';
11279
12055
  import { AppService } from './app.service';
@@ -11504,6 +12280,7 @@ export function TodoList({
11504
12280
 
11505
12281
  // src/templates/todo-example/templates/web-page.ts
11506
12282
  var web_page_default = {
12283
+ when: (s) => s.todoExample && !s.shadcn,
11507
12284
  filename: "apps/web/app/page.tsx",
11508
12285
  template: `'use client';
11509
12286
 
@@ -11735,6 +12512,7 @@ export function TodoList({
11735
12512
 
11736
12513
  // src/templates/todo-example/templates/shadcn-page.ts
11737
12514
  var shadcn_page_default = {
12515
+ when: (s) => s.todoExample && s.shadcn,
11738
12516
  filename: "apps/web/app/page.tsx",
11739
12517
  template: `'use client';
11740
12518
 
@@ -11869,32 +12647,37 @@ var staticDirPath = fileURLToPath(staticDir);
11869
12647
  function getStaticFilePath(name) {
11870
12648
  return fileURLToPath(new URL(`./static/${name}`, import.meta.url));
11871
12649
  }
11872
- var templates = {
11873
- root: root_default,
11874
- web: web_default,
11875
- api: api_default,
11876
- auth: auth_default,
11877
- dbSqlite,
11878
- dbPostgres,
11879
- ui: ui_default,
11880
- shadcnUi: shadcn_ui_default,
11881
- eslintConfig: eslint_config_default4,
11882
- oxc: oxc_default,
11883
- typescriptConfig: typescript_config_default,
11884
- testingJest: testing_jest_default,
11885
- testingVitest: testing_vitest_default,
11886
- deploymentStandalone: deployment_standalone_default,
11887
- deploymentCustomServer: single_process_custom_server_default,
11888
- deploymentSpa: single_process_static_export_default,
11889
- nestDiOnly: nest_di_only_default,
11890
- deploymentStandaloneDi: deployment_standalone_di_default,
11891
- apiControllers: api_controllers_default,
11892
- todoExampleApi,
11893
- todoExampleControllers,
11894
- todoExampleDi,
11895
- todoExampleWeb,
11896
- todoExampleShadcn
11897
- };
12650
+ function selectModules(selection) {
12651
+ const { deployment, nestDiOnly: nestDiOnly2, todoExample, shadcn, database, linter, testing } = selection;
12652
+ const deploymentModule = deployment === "standalone" ? deployment_standalone_default : deployment === "custom-server" ? single_process_custom_server_default : deployment === "spa" ? single_process_static_export_default : null;
12653
+ const webModule = deployment === "spa" ? {
12654
+ ...web_default,
12655
+ templates: web_default.templates.filter(
12656
+ (t) => t.filename !== "apps/web/app/api/auth/[...all]/route.ts"
12657
+ )
12658
+ } : web_default;
12659
+ return [
12660
+ root_default,
12661
+ webModule,
12662
+ api_default,
12663
+ database === "postgres" ? dbPostgres : dbSqlite,
12664
+ auth_default,
12665
+ shadcn ? shadcn_ui_default : ui_default,
12666
+ linter === "oxc" ? oxc_default : eslint_config_default4,
12667
+ typescript_config_default,
12668
+ testing === "vitest" ? testing_vitest_default : testing_jest_default,
12669
+ ...deploymentModule ? [deploymentModule] : [],
12670
+ ...nestDiOnly2 ? [nest_di_only_default] : [api_controllers_default],
12671
+ // nest-di-only overwrites the standalone next.config.js and leaves the
12672
+ // Dockerfile pointing at an api entrypoint DI-only never emits
12673
+ ...nestDiOnly2 && deployment === "standalone" ? [deployment_standalone_di_default] : [],
12674
+ ...todoExample ? [
12675
+ todoExampleApi,
12676
+ ...nestDiOnly2 ? [todoExampleDi] : [todoExampleControllers],
12677
+ shadcn ? todoExampleShadcn : todoExampleWeb
12678
+ ] : []
12679
+ ];
12680
+ }
11898
12681
 
11899
12682
  // src/tasks.ts
11900
12683
  import { randomBytes } from "crypto";
@@ -11953,17 +12736,20 @@ async function updateScripts(destDir, scripts, templateData) {
11953
12736
  );
11954
12737
  }
11955
12738
  }
11956
- async function renderTemplatesToDisk(basePackages, destDir, templateData) {
12739
+ async function renderTemplatesToDisk(basePackages, destDir, templateData, selection) {
11957
12740
  await promises.mkdir(destDir, { recursive: true });
11958
12741
  await basePackages.reduce(async (prev, pkg) => {
11959
12742
  await prev;
11960
- for (const template of pkg.templates) {
12743
+ const applicable = pkg.templates.filter(
12744
+ (template) => template.when?.(selection) ?? true
12745
+ );
12746
+ await applicable.reduce(async (prev2, template) => {
12747
+ await prev2;
11961
12748
  const destPath = path.join(destDir, template.filename);
11962
- const destDirPath = path.dirname(destPath);
11963
- await promises.mkdir(destDirPath, { recursive: true });
12749
+ await promises.mkdir(path.dirname(destPath), { recursive: true });
11964
12750
  const output = await ejs.render(template.template, templateData);
11965
12751
  await promises.writeFile(destPath, output, "utf8");
11966
- }
12752
+ }, Promise.resolve());
11967
12753
  if (pkg.staticFiles) {
11968
12754
  await pkg.staticFiles.reduce(async (prev2, staticFile) => {
11969
12755
  await prev2;
@@ -12027,6 +12813,12 @@ function validateDeploymentCombo(deployment, nestDiOnly2) {
12027
12813
  error: "--deployment spa cannot be combined with --nest-di-only.\nSPA mode statically exports Next.js (output: 'export'), which cannot include the\nAPI route handlers that DI-only mode depends on. Pick one: drop --nest-di-only to\nget SPA mode with NestJS controllers, or drop --deployment spa."
12028
12814
  };
12029
12815
  }
12816
+ if (deployment === "custom-server" && nestDiOnly2) {
12817
+ return {
12818
+ valid: false,
12819
+ error: "--deployment custom-server cannot be combined with --nest-di-only.\nDI-only keeps Next.js as the server and calls Nest in-process, so it overwrites the\nscripts that would run the custom server \u2014 apps/web/server.ts would be generated but\nnever invoked. Both already run Nest inside the Next.js process; pick one."
12820
+ };
12821
+ }
12030
12822
  return { valid: true };
12031
12823
  }
12032
12824
  function validateProjectName(projectName) {
@@ -12068,9 +12860,10 @@ async function scaffold(modules, options) {
12068
12860
  testing: options.testing,
12069
12861
  database: options.database,
12070
12862
  deployment: options.deployment,
12071
- authSecret: randomBytes(32).toString("base64url")
12863
+ authSecret: randomBytes(32).toString("base64url"),
12864
+ versions
12072
12865
  };
12073
- await renderTemplatesToDisk(modules, options.name, templateData);
12866
+ await renderTemplatesToDisk(modules, options.name, templateData, options.selection);
12074
12867
  const packages = modules.map((mod) => mod.packages).filter((ele) => ele !== void 0).flat();
12075
12868
  if (packages.length > 0) {
12076
12869
  await updatePackageJson(options.name, packages, templateData);
@@ -12169,10 +12962,12 @@ async function doInit(options) {
12169
12962
  options: [
12170
12963
  { value: "none", label: "None", hint: "skip" },
12171
12964
  { value: "standalone", label: "Standalone + Dockerfile", hint: "Dockerfiles + docker-compose.yml" },
12172
- { value: "custom-server", label: "Custom Server", hint: "single process, single port" },
12173
- // SPA statically exports Next.js, which can't hold the route
12174
- // handlers DI-only mode runs on
12175
- ...results.nestDiOnly ? [] : [{ value: "spa", label: "SPA Mode", hint: "static export served by NestJS" }]
12965
+ // DI-only already runs Nest inside the Next process, and SPA's static
12966
+ // export can't hold the route handlers DI-only depends on
12967
+ ...results.nestDiOnly ? [] : [
12968
+ { value: "custom-server", label: "Custom Server", hint: "single process, single port" },
12969
+ { value: "spa", label: "SPA Mode", hint: "static export served by NestJS" }
12970
+ ]
12176
12971
  ],
12177
12972
  initialValue: "none"
12178
12973
  })
@@ -12196,40 +12991,28 @@ async function doInit(options) {
12196
12991
  if (!deploymentCombo.valid) {
12197
12992
  throw new Error(deploymentCombo.error);
12198
12993
  }
12199
- const deploymentModule = deployment === "standalone" ? templates.deploymentStandalone : deployment === "custom-server" ? templates.deploymentCustomServer : deployment === "spa" ? templates.deploymentSpa : null;
12200
- const webModule = deployment === "spa" ? {
12201
- ...templates.web,
12202
- templates: templates.web.templates.filter(
12203
- (t) => t.filename !== "apps/web/app/api/auth/[...all]/route.ts"
12204
- )
12205
- } : templates.web;
12206
- const allModules = [
12207
- templates.root,
12208
- webModule,
12209
- templates.api,
12210
- database === "postgres" ? templates.dbPostgres : templates.dbSqlite,
12211
- templates.auth,
12212
- useShadcn ? templates.shadcnUi : templates.ui,
12213
- linter === "oxc" ? templates.oxc : templates.eslintConfig,
12214
- templates.typescriptConfig,
12215
- testing === "vitest" ? templates.testingVitest : templates.testingJest,
12216
- ...deploymentModule ? [deploymentModule] : [],
12217
- ...nestDiOnly2 ? [templates.nestDiOnly] : [templates.apiControllers],
12218
- // nest-di-only overwrites the standalone next.config.js and leaves the
12219
- // Dockerfile pointing at an api entrypoint DI-only never emits
12220
- ...nestDiOnly2 && deployment === "standalone" ? [templates.deploymentStandaloneDi] : [],
12221
- ...todoExample ? [
12222
- templates.todoExampleApi,
12223
- ...nestDiOnly2 ? [templates.todoExampleDi] : [templates.todoExampleControllers],
12224
- useShadcn ? templates.todoExampleShadcn : templates.todoExampleWeb
12225
- ] : []
12226
- ];
12994
+ const selection = {
12995
+ deployment,
12996
+ nestDiOnly: nestDiOnly2,
12997
+ todoExample,
12998
+ shadcn: useShadcn,
12999
+ database,
13000
+ linter,
13001
+ testing
13002
+ };
13003
+ const allModules = selectModules(selection);
12227
13004
  const name = group2.name ?? options.name ?? "";
12228
13005
  const taskBuilder = new TaskBuilder();
12229
13006
  taskBuilder.add({
12230
13007
  title: "Scaffolding project",
12231
13008
  task: async () => {
12232
- await scaffold(allModules, { name, testing, database, deployment });
13009
+ await scaffold(allModules, {
13010
+ name,
13011
+ testing,
13012
+ database,
13013
+ deployment,
13014
+ selection
13015
+ });
12233
13016
  return "Scaffolded.";
12234
13017
  }
12235
13018
  });