better-ts-stack 1.0.8 → 1.1.1

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 (59) hide show
  1. package/dist/builder/configGenerator.d.ts.map +1 -1
  2. package/dist/builder/configGenerator.js +4 -1
  3. package/dist/builder/configGenerator.js.map +1 -1
  4. package/dist/builder/moduleSelector.d.ts.map +1 -1
  5. package/dist/builder/moduleSelector.js +1 -1
  6. package/dist/builder/moduleSelector.js.map +1 -1
  7. package/dist/builder/templateContext.d.ts +1 -1
  8. package/dist/builder/templateContext.d.ts.map +1 -1
  9. package/dist/builder/templateContext.js +1 -1
  10. package/dist/builder/templateContext.js.map +1 -1
  11. package/dist/prompts/stack.d.ts.map +1 -1
  12. package/dist/prompts/stack.js +16 -11
  13. package/dist/prompts/stack.js.map +1 -1
  14. package/dist/types/index.d.ts +8 -3
  15. package/dist/types/index.d.ts.map +1 -1
  16. package/dist/types/index.js +6 -1
  17. package/dist/types/index.js.map +1 -1
  18. package/package.json +1 -1
  19. package/templates/frontend/tanstack/components.json +18 -0
  20. package/templates/frontend/tanstack/config.json +49 -0
  21. package/templates/frontend/tanstack/eslint.config.mjs +23 -0
  22. package/templates/frontend/tanstack/gitignore +38 -0
  23. package/templates/frontend/tanstack/public/favicon.svg +7 -0
  24. package/templates/frontend/tanstack/src/components/ui/button.tsx +51 -0
  25. package/templates/frontend/tanstack/src/components/ui/card.tsx +60 -0
  26. package/templates/frontend/tanstack/src/components/ui/field.tsx +67 -0
  27. package/templates/frontend/tanstack/src/components/ui/input.tsx +18 -0
  28. package/templates/frontend/tanstack/src/lib/utils.ts +6 -0
  29. package/templates/frontend/tanstack/src/routeTree.gen.ts +68 -0
  30. package/templates/frontend/tanstack/src/router.tsx +32 -0
  31. package/templates/frontend/tanstack/src/routes/__root.tsx +70 -0
  32. package/templates/frontend/tanstack/src/routes/index.tsx.hbs +102 -0
  33. package/templates/frontend/tanstack/src/styles/app.css +85 -0
  34. package/templates/frontend/tanstack/tsconfig.json +22 -0
  35. package/templates/frontend/tanstack/vite.config.ts +14 -0
  36. package/templates/modules/auth/tanstack/config.json +33 -0
  37. package/templates/modules/auth/tanstack/src/components/auth/sign-in-form.tsx +135 -0
  38. package/templates/modules/auth/tanstack/src/components/auth/sign-out-button.tsx +49 -0
  39. package/templates/modules/auth/tanstack/src/components/auth/sign-up-form.tsx +153 -0
  40. package/templates/modules/auth/tanstack/src/lib/auth-client.ts +3 -0
  41. package/templates/modules/auth/tanstack/src/lib/auth-functions.ts +12 -0
  42. package/templates/modules/auth/tanstack/src/lib/auth-schema.ts +39 -0
  43. package/templates/modules/auth/tanstack/src/lib/auth.ts.hbs +38 -0
  44. package/templates/modules/auth/tanstack/src/routeTree.gen.ts +140 -0
  45. package/templates/modules/auth/tanstack/src/routes/api/auth/$.ts +16 -0
  46. package/templates/modules/auth/tanstack/src/routes/dashboard.tsx +111 -0
  47. package/templates/modules/auth/tanstack/src/routes/sign-in.tsx +37 -0
  48. package/templates/modules/auth/tanstack/src/routes/sign-up.tsx +37 -0
  49. package/templates/modules/docker/Dockerfile.hbs +125 -80
  50. package/templates/modules/drizzle/tanstack/config.json +26 -0
  51. package/templates/modules/drizzle/tanstack/drizzle.config.ts +13 -0
  52. package/templates/modules/drizzle/tanstack/src/lib/db.ts +13 -0
  53. package/templates/modules/drizzle/tanstack/src/lib/schema.ts.hbs +84 -0
  54. package/templates/modules/prisma/express/config.json +1 -0
  55. package/templates/modules/prisma/nextjs/config.json +1 -0
  56. package/templates/modules/prisma/tanstack/config.json +29 -0
  57. package/templates/modules/prisma/tanstack/prisma/schema.prisma.hbs +91 -0
  58. package/templates/modules/prisma/tanstack/prisma.config.ts +12 -0
  59. package/templates/modules/prisma/tanstack/src/lib/prisma.ts +18 -0
@@ -1,81 +1,126 @@
1
- {{#if (eq framework 'nextjs')}}
2
- # Base stage
3
- FROM node:24-alpine AS base
4
- WORKDIR /app
5
- RUN apk add --no-cache libc6-compat
6
-
7
- # Dependencies stage
8
- FROM base AS deps
9
- COPY package*.json ./
10
- RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
11
-
12
- # Build stage
13
- FROM base AS builder
14
- COPY --from=deps /app/node_modules ./node_modules
15
- COPY . .
16
- {{#if (eq database 'prisma')}}
17
- RUN DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres" npm run build
18
- {{else if (eq database 'mongoose')}}
19
- RUN MONGODB_URI="mongodb://localhost:27017/build" npm run build
20
- {{else}}
21
- RUN npm run build
22
- {{/if}}
23
-
24
- # Production stage
25
- FROM node:24-alpine AS runner
26
- WORKDIR /app
27
- ENV NODE_ENV=production
28
-
29
- RUN addgroup --system --gid 1001 nodejs && \
30
- adduser --system --uid 1001 nextjs
31
-
32
- COPY --from=builder /app/public ./public
33
- COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
34
- COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
35
-
36
- USER nextjs
37
- EXPOSE {{port}}
38
- ENV PORT={{port}} HOSTNAME=0.0.0.0
39
-
40
- CMD ["node", "server.js"]
41
-
42
- {{else}}
43
- # Build stage
44
- FROM node:24-alpine AS builder
45
- WORKDIR /app
46
-
47
- COPY package*.json ./
48
- RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
49
-
50
- COPY . .
51
-
52
- # Only build if package.json has a build script
53
- {{#if (eq database 'prisma')}}
54
- RUN DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres" npm run build
55
- {{else if (eq database 'mongoose')}}
56
- RUN MONGODB_URI="mongodb://localhost:27017/build" npm run build
57
- {{else}}
58
- RUN npm run build
59
- {{/if}}
60
-
61
- # Production stage
62
- FROM node:24-alpine
63
- WORKDIR /app
64
- ENV NODE_ENV=production
65
-
66
- # Create non-root user for security
67
- RUN addgroup --system --gid 1001 nodejs && \
68
- adduser --system --uid 1001 expressuser
69
-
70
- COPY package*.json ./
71
- RUN if [ -f package-lock.json ]; then npm ci --omit=dev; else npm install --omit=dev; fi
72
-
73
- # Copy built files (if TypeScript) or source files (if JavaScript)
74
- COPY --from=builder --chown=expressuser:nodejs /app/dist ./dist
75
-
76
- USER expressuser
77
- EXPOSE {{port}}
78
- ENV PORT={{port}}
79
-
80
- CMD ["node", "dist/index.js"]
1
+ {{#if (eq framework 'nextjs')}}
2
+ # Base stage
3
+ FROM node:24-alpine AS base
4
+ WORKDIR /app
5
+ RUN apk add --no-cache libc6-compat
6
+
7
+ # Dependencies stage
8
+ FROM base AS deps
9
+ COPY package*.json ./
10
+ RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
11
+
12
+ # Build stage
13
+ FROM base AS builder
14
+ COPY --from=deps /app/node_modules ./node_modules
15
+ COPY . .
16
+ {{#if (eq database 'prisma')}}
17
+ RUN DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres" npm run build
18
+ {{else if (eq database 'mongoose')}}
19
+ RUN MONGODB_URI="mongodb://localhost:27017/build" npm run build
20
+ {{else}}
21
+ RUN npm run build
22
+ {{/if}}
23
+
24
+ # Production stage
25
+ FROM node:24-alpine AS runner
26
+ WORKDIR /app
27
+ ENV NODE_ENV=production
28
+
29
+ RUN addgroup --system --gid 1001 nodejs && \
30
+ adduser --system --uid 1001 nextjs
31
+
32
+ COPY --from=builder /app/public ./public
33
+ COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
34
+ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
35
+
36
+ USER nextjs
37
+ EXPOSE {{port}}
38
+ ENV PORT={{port}} HOSTNAME=0.0.0.0
39
+
40
+ CMD ["node", "server.js"]
41
+
42
+ {{else if (eq framework 'tanstack')}}
43
+ # Build stage
44
+ FROM node:24-alpine AS builder
45
+ WORKDIR /app
46
+
47
+ COPY package*.json ./
48
+ RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
49
+
50
+ COPY . .
51
+
52
+ # Only build if package.json has a build script
53
+ {{#if (eq database 'prisma')}}
54
+ RUN DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres" npm run build
55
+ {{else if (eq database 'mongoose')}}
56
+ RUN MONGODB_URI="mongodb://localhost:27017/build" npm run build
57
+ {{else}}
58
+ RUN npm run build
59
+ {{/if}}
60
+
61
+ # Production stage
62
+ FROM node:24-alpine
63
+ WORKDIR /app
64
+ ENV NODE_ENV=production
65
+
66
+ # Create non-root user for security
67
+ RUN addgroup --system --gid 1001 nodejs && \
68
+ adduser --system --uid 1001 tanstackuser
69
+
70
+ COPY package*.json ./
71
+ RUN if [ -f package-lock.json ]; then npm ci --omit=dev; else npm install --omit=dev; fi
72
+
73
+ # Copy built output (dist/server/server.js + dist/client)
74
+ COPY --from=builder --chown=tanstackuser:nodejs /app/dist ./dist
75
+
76
+ # Include the Prisma client generated during the build stage
77
+ {{#if (eq database 'prisma')}}
78
+ COPY --from=builder --chown=tanstackuser:nodejs /app/generated ./generated
79
+ {{/if}}
80
+
81
+ USER tanstackuser
82
+ EXPOSE {{port}}
83
+ ENV PORT={{port}}
84
+
85
+ CMD ["node_modules/.bin/srvx", "--prod", "-s", "../client", "dist/server/server.js"]
86
+
87
+ {{else}}
88
+ # Build stage
89
+ FROM node:24-alpine AS builder
90
+ WORKDIR /app
91
+
92
+ COPY package*.json ./
93
+ RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
94
+
95
+ COPY . .
96
+
97
+ # Only build if package.json has a build script
98
+ {{#if (eq database 'prisma')}}
99
+ RUN DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres" npm run build
100
+ {{else if (eq database 'mongoose')}}
101
+ RUN MONGODB_URI="mongodb://localhost:27017/build" npm run build
102
+ {{else}}
103
+ RUN npm run build
104
+ {{/if}}
105
+
106
+ # Production stage
107
+ FROM node:24-alpine
108
+ WORKDIR /app
109
+ ENV NODE_ENV=production
110
+
111
+ # Create non-root user for security
112
+ RUN addgroup --system --gid 1001 nodejs && \
113
+ adduser --system --uid 1001 expressuser
114
+
115
+ COPY package*.json ./
116
+ RUN if [ -f package-lock.json ]; then npm ci --omit=dev; else npm install --omit=dev; fi
117
+
118
+ # Copy built files (if TypeScript) or source files (if JavaScript)
119
+ COPY --from=builder --chown=expressuser:nodejs /app/dist ./dist
120
+
121
+ USER expressuser
122
+ EXPOSE {{port}}
123
+ ENV PORT={{port}}
124
+
125
+ CMD ["node", "dist/index.js"]
81
126
  {{/if}}
@@ -0,0 +1,26 @@
1
+ {
2
+ "id": "drizzle",
3
+ "name": "Drizzle ORM",
4
+ "description": "Drizzle ORM for TanStack Start with PostgreSQL",
5
+ "type": "database",
6
+ "dependencies": {
7
+ "drizzle-orm": "^0.45.2",
8
+ "pg": "^8.23.0",
9
+ "dotenv": "^17.4.2"
10
+ },
11
+ "devDependencies": {
12
+ "drizzle-kit": "^0.31.10",
13
+ "@types/pg": "^8.23.1"
14
+ },
15
+ "scripts": {
16
+ "db:generate": "drizzle-kit generate",
17
+ "db:migrate": "drizzle-kit migrate",
18
+ "db:studio": "drizzle-kit studio"
19
+ },
20
+ "envVars": {
21
+ "DATABASE_URL": "postgresql://user:password@localhost:5432/mydb?schema=public"
22
+ },
23
+ "templateFiles": [
24
+ "src/lib/schema.ts.hbs"
25
+ ]
26
+ }
@@ -0,0 +1,13 @@
1
+ import { defineConfig } from "drizzle-kit";
2
+ import { config } from "dotenv";
3
+
4
+ config({ path: ".env" });
5
+
6
+ export default defineConfig({
7
+ schema: "./src/lib/schema.ts",
8
+ out: "./migrations",
9
+ dialect: "postgresql",
10
+ dbCredentials: {
11
+ url: process.env.DATABASE_URL!,
12
+ },
13
+ });
@@ -0,0 +1,13 @@
1
+ import { config } from "dotenv";
2
+ import { drizzle } from "drizzle-orm/node-postgres";
3
+ import { Pool } from "pg";
4
+
5
+ import * as schema from "./schema";
6
+
7
+ config({ path: ".env" }); // or .env.local
8
+
9
+ const pool = new Pool({
10
+ connectionString: process.env.DATABASE_URL,
11
+ });
12
+
13
+ export const db = drizzle(pool, { schema });
@@ -0,0 +1,84 @@
1
+ {{#if useAuth}}
2
+ import { boolean, pgTable, text, timestamp, uniqueIndex } from "drizzle-orm/pg-core";
3
+
4
+ export const user = pgTable("user", {
5
+ id: text("id").primaryKey(),
6
+ name: text("name").notNull(),
7
+ email: text("email").notNull().unique(),
8
+ emailVerified: boolean("email_verified").notNull().default(false),
9
+ image: text("image"),
10
+ createdAt: timestamp("created_at", { withTimezone: true })
11
+ .notNull()
12
+ .defaultNow(),
13
+ updatedAt: timestamp("updated_at", { withTimezone: true })
14
+ .notNull()
15
+ .defaultNow(),
16
+ });
17
+
18
+ export const session = pgTable("session", {
19
+ id: text("id").primaryKey(),
20
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
21
+ token: text("token").notNull().unique(),
22
+ createdAt: timestamp("created_at", { withTimezone: true })
23
+ .notNull()
24
+ .defaultNow(),
25
+ updatedAt: timestamp("updated_at", { withTimezone: true })
26
+ .notNull()
27
+ .defaultNow(),
28
+ ipAddress: text("ip_address"),
29
+ userAgent: text("user_agent"),
30
+ userId: text("user_id")
31
+ .notNull()
32
+ .references(() => user.id, { onDelete: "cascade" }),
33
+ });
34
+
35
+ export const account = pgTable("account", {
36
+ id: text("id").primaryKey(),
37
+ accountId: text("account_id").notNull(),
38
+ providerId: text("provider_id").notNull(),
39
+ userId: text("user_id")
40
+ .notNull()
41
+ .references(() => user.id, { onDelete: "cascade" }),
42
+ accessToken: text("access_token"),
43
+ refreshToken: text("refresh_token"),
44
+ idToken: text("id_token"),
45
+ accessTokenExpiresAt: timestamp("access_token_expires_at", {
46
+ withTimezone: true,
47
+ }),
48
+ refreshTokenExpiresAt: timestamp("refresh_token_expires_at", {
49
+ withTimezone: true,
50
+ }),
51
+ scope: text("scope"),
52
+ password: text("password"),
53
+ createdAt: timestamp("created_at", { withTimezone: true })
54
+ .notNull()
55
+ .defaultNow(),
56
+ updatedAt: timestamp("updated_at", { withTimezone: true })
57
+ .notNull()
58
+ .defaultNow(),
59
+ }, (table) => [uniqueIndex("account_provider_account_id_unique").on(table.providerId, table.accountId)]);
60
+
61
+ export const verification = pgTable("verification", {
62
+ id: text("id").primaryKey(),
63
+ identifier: text("identifier").notNull(),
64
+ value: text("value").notNull(),
65
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
66
+ createdAt: timestamp("created_at", { withTimezone: true })
67
+ .notNull()
68
+ .defaultNow(),
69
+ updatedAt: timestamp("updated_at", { withTimezone: true })
70
+ .notNull()
71
+ .defaultNow(),
72
+ });
73
+ {{else}}
74
+ import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
75
+
76
+ export const users = pgTable("users", {
77
+ id: uuid("id").primaryKey().defaultRandom(),
78
+ email: text("email").notNull().unique(),
79
+ name: text("name"),
80
+ password: text("password").notNull(),
81
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
82
+ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow(),
83
+ });
84
+ {{/if}}
@@ -14,6 +14,7 @@
14
14
  "prisma:generate": "prisma generate",
15
15
  "prisma:migrate": "prisma migrate dev",
16
16
  "prisma:studio": "prisma studio",
17
+ "pretype:check": "prisma generate",
17
18
  "prebuild": "prisma generate"
18
19
  },
19
20
  "envVars": {
@@ -15,6 +15,7 @@
15
15
  "prisma:generate": "prisma generate",
16
16
  "prisma:migrate": "prisma migrate dev",
17
17
  "prisma:studio": "prisma studio",
18
+ "pretype:check": "prisma generate",
18
19
  "prebuild": "prisma generate"
19
20
  },
20
21
  "envVars": {
@@ -0,0 +1,29 @@
1
+ {
2
+ "id": "prisma",
3
+ "name": "Prisma ORM",
4
+ "description": "Prisma ORM for TanStack Start with PostgreSQL",
5
+ "type": "database",
6
+ "dependencies": {
7
+ "@prisma/client": "^7.10.0",
8
+ "@prisma/adapter-pg": "^7.10.0"
9
+ },
10
+ "devDependencies": {
11
+ "prisma": "^7.10.0",
12
+ "dotenv": "^17.4.2"
13
+ },
14
+ "scripts": {
15
+ "prisma:generate": "prisma generate",
16
+ "prisma:migrate": "prisma migrate dev",
17
+ "prisma:studio": "prisma studio",
18
+ "pretype:check": "prisma generate",
19
+ "prebuild": "prisma generate"
20
+ },
21
+ "envVars": {
22
+ "DATABASE_URL": "postgresql://postgres:postgres@localhost:5432/postgres?schema=public"
23
+ },
24
+ "templateFiles": ["prisma/schema.prisma.hbs"],
25
+ "overrides": {
26
+ "deepmerge-ts": "^8.0.2",
27
+ "mysql2": "^3.24.3"
28
+ }
29
+ }
@@ -0,0 +1,91 @@
1
+ // Prisma schema file
2
+ // Learn more: https://pris.ly/d/prisma-schema
3
+
4
+ generator client {
5
+ provider = "prisma-client"
6
+ output = "../generated"
7
+ }
8
+
9
+ datasource db {
10
+ provider = "postgresql"
11
+ }
12
+
13
+ {{#if useAuth}}
14
+
15
+ model User {
16
+ id String @id
17
+ name String
18
+ email String
19
+ emailVerified Boolean @default(false)
20
+ image String?
21
+ createdAt DateTime @default(now())
22
+ updatedAt DateTime @updatedAt
23
+ sessions Session[]
24
+ accounts Account[]
25
+
26
+ @@unique([email])
27
+ @@map("user")
28
+ }
29
+
30
+ model Session {
31
+ id String @id
32
+ expiresAt DateTime
33
+ token String
34
+ createdAt DateTime @default(now())
35
+ updatedAt DateTime @updatedAt
36
+ ipAddress String?
37
+ userAgent String?
38
+ userId String
39
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
40
+
41
+ @@unique([token])
42
+ @@index([userId])
43
+ @@map("session")
44
+ }
45
+
46
+ model Account {
47
+ id String @id
48
+ accountId String
49
+ providerId String
50
+ userId String
51
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
52
+ accessToken String?
53
+ refreshToken String?
54
+ idToken String?
55
+ accessTokenExpiresAt DateTime?
56
+ refreshTokenExpiresAt DateTime?
57
+ scope String?
58
+ password String?
59
+ createdAt DateTime @default(now())
60
+ updatedAt DateTime @updatedAt
61
+
62
+ @@index([userId])
63
+ @@unique([providerId, accountId])
64
+ @@map("account")
65
+ }
66
+
67
+ model Verification {
68
+ id String @id
69
+ identifier String
70
+ value String
71
+ expiresAt DateTime
72
+ createdAt DateTime @default(now())
73
+ updatedAt DateTime @updatedAt
74
+
75
+ @@index([identifier])
76
+ @@map("verification")
77
+ }
78
+
79
+ {{else}}
80
+ // Sample User model
81
+ model User {
82
+ id String @id @default(uuid())
83
+ email String @unique
84
+ name String?
85
+ password String
86
+ createdAt DateTime @default(now())
87
+ updatedAt DateTime @updatedAt
88
+
89
+ @@map("users")
90
+ }
91
+ {{/if}}
@@ -0,0 +1,12 @@
1
+ import "dotenv/config";
2
+ import { defineConfig, env } from "prisma/config";
3
+
4
+ export default defineConfig({
5
+ schema: "prisma/schema.prisma",
6
+ migrations: {
7
+ path: "prisma/migrations",
8
+ },
9
+ datasource: {
10
+ url: env("DATABASE_URL"),
11
+ },
12
+ });
@@ -0,0 +1,18 @@
1
+ import { PrismaPg } from "@prisma/adapter-pg";
2
+
3
+ import { PrismaClient } from "../../generated/client";
4
+
5
+ const globalForPrisma = global as unknown as {
6
+ prisma: PrismaClient;
7
+ };
8
+ const adapter = new PrismaPg({
9
+ connectionString: process.env.DATABASE_URL,
10
+ });
11
+ const prisma =
12
+ globalForPrisma.prisma ||
13
+ new PrismaClient({
14
+ adapter,
15
+ });
16
+ if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
17
+
18
+ export default prisma;