create-solostack 1.0.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.
@@ -0,0 +1,365 @@
1
+ import path from 'path';
2
+ import { writeFile, ensureDir } from '../utils/files.js';
3
+
4
+ /**
5
+ * Generates Prisma database configuration
6
+ * @param {string} projectPath - Path where the project is located
7
+ * @param {string} database - Database type (currently only PostgreSQL supported)
8
+ */
9
+ export async function generateDatabase(projectPath, database) {
10
+ // Create prisma directory
11
+ await ensureDir(path.join(projectPath, 'prisma'));
12
+
13
+ // Generate schema.prisma
14
+ const schemaPrisma = `generator client {
15
+ provider = "prisma-client-js"
16
+ }
17
+
18
+ datasource db {
19
+ provider = "postgresql"
20
+ url = env("DATABASE_URL")
21
+ }
22
+
23
+ model User {
24
+ id String @id @default(cuid())
25
+ email String @unique
26
+ name String?
27
+ emailVerified DateTime?
28
+ image String?
29
+ password String? // For email/password auth
30
+ role Role @default(USER)
31
+ stripeCustomerId String? @unique
32
+ subscription Subscription?
33
+ createdAt DateTime @default(now())
34
+ updatedAt DateTime @updatedAt
35
+
36
+ accounts Account[]
37
+ sessions Session[]
38
+ payments Payment[]
39
+ }
40
+
41
+ model Account {
42
+ userId String
43
+ type String
44
+ provider String
45
+ providerAccountId String
46
+ refresh_token String? @db.Text
47
+ access_token String? @db.Text
48
+ expires_at Int?
49
+ token_type String?
50
+ scope String?
51
+ id_token String? @db.Text
52
+ session_state String?
53
+
54
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
55
+
56
+ @@unique([provider, providerAccountId])
57
+ @@index([userId])
58
+ }
59
+
60
+ model Session {
61
+ sessionToken String @unique
62
+ userId String
63
+ expires DateTime
64
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
65
+
66
+ @@index([userId])
67
+ }
68
+
69
+ model VerificationToken {
70
+ identifier String
71
+ token String @unique
72
+ expires DateTime
73
+
74
+ @@unique([identifier, token])
75
+ }
76
+
77
+ model Subscription {
78
+ id String @id @default(cuid())
79
+ userId String @unique
80
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
81
+ stripeSubscriptionId String @unique
82
+ stripePriceId String
83
+ status SubscriptionStatus
84
+ currentPeriodStart DateTime
85
+ currentPeriodEnd DateTime
86
+ cancelAtPeriodEnd Boolean @default(false)
87
+ createdAt DateTime @default(now())
88
+ updatedAt DateTime @updatedAt
89
+ }
90
+
91
+ model Payment {
92
+ id String @id @default(cuid())
93
+ userId String
94
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
95
+ stripePaymentId String @unique
96
+ amount Int // In cents
97
+ currency String @default("usd")
98
+ status String
99
+ createdAt DateTime @default(now())
100
+
101
+ @@index([userId])
102
+ }
103
+
104
+ model StripeEvent {
105
+ id String @id @default(cuid())
106
+ eventId String @unique // Stripe event ID
107
+ type String // Event type (e.g., "checkout.session.completed")
108
+ processed Boolean @default(false)
109
+ createdAt DateTime @default(now())
110
+
111
+ @@index([eventId])
112
+ @@index([processed])
113
+ }
114
+
115
+ enum Role {
116
+ USER
117
+ ADMIN
118
+ }
119
+
120
+ enum SubscriptionStatus {
121
+ ACTIVE
122
+ CANCELED
123
+ PAST_DUE
124
+ TRIALING
125
+ INCOMPLETE
126
+ }
127
+ `;
128
+
129
+ await writeFile(path.join(projectPath, 'prisma/schema.prisma'), schemaPrisma);
130
+
131
+ // Generate database client
132
+ const dbClient = `import { PrismaClient } from '@prisma/client';
133
+
134
+ const globalForPrisma = globalThis as unknown as {
135
+ prisma: PrismaClient | undefined;
136
+ };
137
+
138
+ export const db = globalForPrisma.prisma ?? new PrismaClient();
139
+
140
+ if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = db;
141
+ `;
142
+
143
+ await writeFile(path.join(projectPath, 'src/lib/db.ts'), dbClient);
144
+
145
+ // Generate seed script
146
+ const seedScript = `import { PrismaClient } from '@prisma/client';
147
+ import bcrypt from 'bcryptjs';
148
+
149
+ const prisma = new PrismaClient();
150
+
151
+ async function main() {
152
+ console.log('🌱 Seeding database...');
153
+
154
+ // Create a test user
155
+ const hashedPassword = await bcrypt.hash('password123', 10);
156
+
157
+ const user = await prisma.user.upsert({
158
+ where: { email: 'test@example.com' },
159
+ update: {},
160
+ create: {
161
+ email: 'test@example.com',
162
+ name: 'Test User',
163
+ password: hashedPassword,
164
+ emailVerified: new Date(),
165
+ },
166
+ });
167
+
168
+ console.log('✅ Created test user:', user.email);
169
+
170
+ // Create an admin user
171
+ const admin = await prisma.user.upsert({
172
+ where: { email: 'admin@example.com' },
173
+ update: {},
174
+ create: {
175
+ email: 'admin@example.com',
176
+ name: 'Admin User',
177
+ password: hashedPassword,
178
+ emailVerified: new Date(),
179
+ role: 'ADMIN',
180
+ },
181
+ });
182
+
183
+ console.log('✅ Created admin user:', admin.email);
184
+
185
+ console.log('🎉 Seeding complete!');
186
+ }
187
+
188
+ main()
189
+ .catch((e) => {
190
+ console.error('❌ Seeding failed:', e);
191
+ process.exit(1);
192
+ })
193
+ .finally(async () => {
194
+ await prisma.$disconnect();
195
+ });
196
+ `;
197
+
198
+ await writeFile(path.join(projectPath, 'prisma/seed.ts'), seedScript);
199
+
200
+ // Generate database migration guide
201
+ const dbGuide = `# Database Setup Guide
202
+
203
+ ## Initial Setup
204
+
205
+ ### 1. Set up your PostgreSQL database
206
+
207
+ **Option A: Local PostgreSQL**
208
+ \`\`\`bash
209
+ # Install PostgreSQL (if not already installed)
210
+ # macOS
211
+ brew install postgresql
212
+ brew services start postgresql
213
+
214
+ # Ubuntu/Debian
215
+ sudo apt-get install postgresql
216
+ sudo service postgresql start
217
+
218
+ # Windows
219
+ # Download from https://www.postgresql.org/download/windows/
220
+ \`\`\`
221
+
222
+ Create a database:
223
+ \`\`\`bash
224
+ psql postgres
225
+ CREATE DATABASE your_database_name;
226
+ CREATE USER your_user WITH PASSWORD 'your_password';
227
+ GRANT ALL PRIVILEGES ON DATABASE your_database_name TO your_user;
228
+ \\q
229
+ \`\`\`
230
+
231
+ **Option B: Cloud Database (Recommended for Production)**
232
+ - [Neon](https://neon.tech) - Free tier with PostgreSQL
233
+ - [Supabase](https://supabase.com) - Free tier with PostgreSQL
234
+ - [Railway](https://railway.app) - Easy PostgreSQL deployment
235
+ - [Vercel Postgres](https://vercel.com/storage/postgres) - Serverless PostgreSQL
236
+
237
+ ### 2. Update your .env file
238
+
239
+ \`\`\`env
240
+ DATABASE_URL="postgresql://user:password@localhost:5432/dbname"
241
+ # Or for cloud:
242
+ # DATABASE_URL="postgresql://user:password@host:5432/dbname?sslmode=require"
243
+ \`\`\`
244
+
245
+ ### 3. Push the schema to your database
246
+
247
+ \`\`\`bash
248
+ npm run db:push
249
+ \`\`\`
250
+
251
+ This command:
252
+ - Creates all tables based on your schema
253
+ - Sets up indexes for performance
254
+ - Applies constraints and relationships
255
+
256
+ ### 4. Seed the database (optional)
257
+
258
+ \`\`\`bash
259
+ npm run db:seed
260
+ \`\`\`
261
+
262
+ This creates:
263
+ - Test user: test@example.com (password: password123)
264
+ - Admin user: admin@example.com (password: password123)
265
+
266
+ ## Making Schema Changes
267
+
268
+ ### 1. Edit prisma/schema.prisma
269
+
270
+ Add or modify models as needed.
271
+
272
+ ### 2. Apply changes
273
+
274
+ **For development:**
275
+ \`\`\`bash
276
+ npm run db:push
277
+ \`\`\`
278
+
279
+ **For production (with migrations):**
280
+ \`\`\`bash
281
+ npx prisma migrate dev --name your_migration_name
282
+ \`\`\`
283
+
284
+ This creates a migration file in \`prisma/migrations/\`.
285
+
286
+ ### 3. Apply migrations to production
287
+
288
+ \`\`\`bash
289
+ npx prisma migrate deploy
290
+ \`\`\`
291
+
292
+ ## Prisma Studio
293
+
294
+ Inspect and edit your database with a visual interface:
295
+
296
+ \`\`\`bash
297
+ npm run db:studio
298
+ \`\`\`
299
+
300
+ Opens at http://localhost:5555
301
+
302
+ ## Common Commands
303
+
304
+ \`\`\`bash
305
+ # Generate Prisma Client after schema changes
306
+ npx prisma generate
307
+
308
+ # Format schema file
309
+ npx prisma format
310
+
311
+ # Check if database is in sync with schema
312
+ npx prisma db pull
313
+
314
+ # Reset database (⚠️ deletes all data)
315
+ npx prisma migrate reset
316
+
317
+ # View database structure
318
+ npx prisma db pull
319
+ \`\`\`
320
+
321
+ ## Backup & Restore
322
+
323
+ ### Backup
324
+ \`\`\`bash
325
+ pg_dump -U your_user -d your_database > backup.sql
326
+ \`\`\`
327
+
328
+ ### Restore
329
+ \`\`\`bash
330
+ psql -U your_user -d your_database < backup.sql
331
+ \`\`\`
332
+
333
+ ## Troubleshooting
334
+
335
+ ### Connection Issues
336
+ - Verify DATABASE_URL is correct
337
+ - Check if PostgreSQL is running
338
+ - Ensure database exists
339
+ - Check firewall settings for remote connections
340
+
341
+ ### Migration Conflicts
342
+ \`\`\`bash
343
+ # Reset migrations (development only)
344
+ npx prisma migrate reset
345
+
346
+ # Mark migration as applied without running
347
+ npx prisma migrate resolve --applied migration_name
348
+ \`\`\`
349
+
350
+ ### Performance
351
+ - Add indexes for frequently queried fields
352
+ - Use \`@@index\` in your schema
353
+ - Monitor with \`EXPLAIN ANALYZE\` in PostgreSQL
354
+
355
+ ## Best Practices
356
+
357
+ 1. **Always backup before major migrations**
358
+ 2. **Test migrations on staging first**
359
+ 3. **Use migrations (not db push) in production**
360
+ 4. **Keep DATABASE_URL in .env, never commit it**
361
+ 5. **Use connection pooling for serverless (e.g., Prisma Data Proxy)**
362
+ `;
363
+
364
+ await writeFile(path.join(projectPath, 'prisma/DATABASE_GUIDE.md'), dbGuide);
365
+ }