@amirulabu/create-recurring-rabbit-app 0.0.0-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +2 -0
- package/dist/index.js +592 -0
- package/package.json +43 -0
- package/templates/default/.editorconfig +21 -0
- package/templates/default/.env.example +15 -0
- package/templates/default/.eslintrc.json +35 -0
- package/templates/default/.prettierrc.json +7 -0
- package/templates/default/README.md +346 -0
- package/templates/default/app.config.ts +20 -0
- package/templates/default/docs/adding-features.md +439 -0
- package/templates/default/docs/adr/001-use-sqlite-for-development-database.md +22 -0
- package/templates/default/docs/adr/002-use-tanstack-start-over-nextjs.md +22 -0
- package/templates/default/docs/adr/003-use-better-auth-over-nextauth.md +22 -0
- package/templates/default/docs/adr/004-use-drizzle-over-prisma.md +22 -0
- package/templates/default/docs/adr/005-use-trpc-for-api-layer.md +22 -0
- package/templates/default/docs/adr/006-use-tailwind-css-v4-with-shadcn-ui.md +22 -0
- package/templates/default/docs/architecture.md +241 -0
- package/templates/default/docs/database.md +376 -0
- package/templates/default/docs/deployment.md +435 -0
- package/templates/default/docs/troubleshooting.md +668 -0
- package/templates/default/drizzle/migrations/0001_initial_schema.sql +39 -0
- package/templates/default/drizzle/migrations/meta/0001_snapshot.json +225 -0
- package/templates/default/drizzle/migrations/meta/_journal.json +12 -0
- package/templates/default/drizzle.config.ts +10 -0
- package/templates/default/lighthouserc.json +78 -0
- package/templates/default/src/app/__root.tsx +32 -0
- package/templates/default/src/app/api/auth/$.ts +15 -0
- package/templates/default/src/app/api/trpc.server.ts +12 -0
- package/templates/default/src/app/auth/forgot-password.tsx +107 -0
- package/templates/default/src/app/auth/login.tsx +34 -0
- package/templates/default/src/app/auth/register.tsx +34 -0
- package/templates/default/src/app/auth/reset-password.tsx +171 -0
- package/templates/default/src/app/auth/verify-email.tsx +111 -0
- package/templates/default/src/app/dashboard/index.tsx +122 -0
- package/templates/default/src/app/dashboard/settings.tsx +161 -0
- package/templates/default/src/app/globals.css +55 -0
- package/templates/default/src/app/index.tsx +83 -0
- package/templates/default/src/components/features/auth/login-form.tsx +172 -0
- package/templates/default/src/components/features/auth/register-form.tsx +202 -0
- package/templates/default/src/components/layout/dashboard-layout.tsx +27 -0
- package/templates/default/src/components/layout/header.tsx +29 -0
- package/templates/default/src/components/layout/sidebar.tsx +38 -0
- package/templates/default/src/components/ui/button.tsx +57 -0
- package/templates/default/src/components/ui/card.tsx +79 -0
- package/templates/default/src/components/ui/input.tsx +24 -0
- package/templates/default/src/lib/api.ts +42 -0
- package/templates/default/src/lib/auth.ts +292 -0
- package/templates/default/src/lib/email.ts +221 -0
- package/templates/default/src/lib/env.ts +119 -0
- package/templates/default/src/lib/hydration-timing.ts +289 -0
- package/templates/default/src/lib/monitoring.ts +336 -0
- package/templates/default/src/lib/utils.ts +6 -0
- package/templates/default/src/server/api/root.ts +10 -0
- package/templates/default/src/server/api/routers/dashboard.ts +37 -0
- package/templates/default/src/server/api/routers/user.ts +31 -0
- package/templates/default/src/server/api/trpc.ts +132 -0
- package/templates/default/src/server/auth/config.ts +241 -0
- package/templates/default/src/server/db/index.ts +153 -0
- package/templates/default/src/server/db/migrate.ts +125 -0
- package/templates/default/src/server/db/schema.ts +170 -0
- package/templates/default/src/server/db/seed.ts +130 -0
- package/templates/default/src/types/global.d.ts +25 -0
- package/templates/default/tailwind.config.js +46 -0
- package/templates/default/tsconfig.json +36 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Seeding Module
|
|
3
|
+
*
|
|
4
|
+
* This module provides functionality to populate the database with initial
|
|
5
|
+
* sample data for development and testing purposes. It is designed to be
|
|
6
|
+
* idempotent - running multiple times will not create duplicate records.
|
|
7
|
+
*
|
|
8
|
+
* Database Design Decisions:
|
|
9
|
+
* - Seeds are designed for development environments, not production
|
|
10
|
+
* - Sample users have verified email addresses for immediate testing
|
|
11
|
+
* - Uses INSERT with RETURNING to confirm successful inserts
|
|
12
|
+
* - Handles UNIQUE constraint violations gracefully (idempotent)
|
|
13
|
+
*
|
|
14
|
+
* Migration Strategy:
|
|
15
|
+
* - Run seeding after migrations to ensure schema is ready
|
|
16
|
+
* - Seed data should be versioned alongside schema changes
|
|
17
|
+
* - For production, consider using a separate data migration system
|
|
18
|
+
*
|
|
19
|
+
* Development vs Production:
|
|
20
|
+
* - Development:
|
|
21
|
+
* - Seeds run automatically on application startup (if configured)
|
|
22
|
+
* - Provides realistic test data without manual data entry
|
|
23
|
+
* - Production:
|
|
24
|
+
* - Never run automatic seeds in production
|
|
25
|
+
* - Use controlled data migration scripts for production data
|
|
26
|
+
* - Seed data should never contain real user credentials
|
|
27
|
+
*
|
|
28
|
+
* Seeding Best Practices:
|
|
29
|
+
* - Keep seeds simple and focused on essential test data
|
|
30
|
+
* - Make seeds idempotent to allow safe re-running
|
|
31
|
+
* - Use meaningful sample data that reflects real usage patterns
|
|
32
|
+
* - Document what data is being seeded for team reference
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import { db } from './index'
|
|
36
|
+
import { users } from './schema'
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Seeds the database with sample data for development and testing
|
|
40
|
+
*
|
|
41
|
+
* This function creates sample user records in the database. It is designed to be
|
|
42
|
+
* idempotent - if sample data already exists (same email addresses), it will
|
|
43
|
+
* gracefully skip insertion without errors.
|
|
44
|
+
*
|
|
45
|
+
* Purpose:
|
|
46
|
+
* - Provide initial data for development and testing environments
|
|
47
|
+
* - Enable immediate testing without manual data entry
|
|
48
|
+
* - Ensure consistent test data across different development setups
|
|
49
|
+
*
|
|
50
|
+
* Parameters:
|
|
51
|
+
* - None (uses predefined sample data)
|
|
52
|
+
*
|
|
53
|
+
* Return Value:
|
|
54
|
+
* - Promise<void>: Resolves when seeding completes or is skipped
|
|
55
|
+
*
|
|
56
|
+
* Side Effects:
|
|
57
|
+
* - Inserts sample user records into the users table
|
|
58
|
+
* - May throw errors for unexpected database failures
|
|
59
|
+
*
|
|
60
|
+
* Error Handling:
|
|
61
|
+
* - UNIQUE constraint violations: Gracefully skipped (seed data exists)
|
|
62
|
+
* - Other errors: Re-thrown with logging for debugging
|
|
63
|
+
* - Script exit(1) on unrecoverable errors
|
|
64
|
+
*
|
|
65
|
+
* Example Usage:
|
|
66
|
+
* ```typescript
|
|
67
|
+
* import { seedDatabase } from './db/seed'
|
|
68
|
+
*
|
|
69
|
+
* async function initializeDevEnvironment() {
|
|
70
|
+
* await seedDatabase()
|
|
71
|
+
* console.log('Development environment ready')
|
|
72
|
+
* }
|
|
73
|
+
*
|
|
74
|
+
* initializeDevEnvironment()
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* CLI Usage:
|
|
78
|
+
* ```bash
|
|
79
|
+
* # Run seed via npm script
|
|
80
|
+
* pnpm db:seed
|
|
81
|
+
*
|
|
82
|
+
* # Or run directly with Node
|
|
83
|
+
* node -r dotenv/config dist/db/seed.js
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* Notes:
|
|
87
|
+
* - Seed data is automatically executed when this module is loaded
|
|
88
|
+
* - Sample users have emailVerified set to true for immediate testing
|
|
89
|
+
* - Email addresses use example.com domain (reserved for testing)
|
|
90
|
+
*
|
|
91
|
+
* @throws {Error} If database connection fails
|
|
92
|
+
* @throws {Error} If database insert fails for reasons other than UNIQUE constraint
|
|
93
|
+
*/
|
|
94
|
+
export async function seedDatabase() {
|
|
95
|
+
console.log('Seeding database with sample data...')
|
|
96
|
+
|
|
97
|
+
const sampleUsers = [
|
|
98
|
+
{
|
|
99
|
+
email: 'demo@example.com',
|
|
100
|
+
name: 'Demo User',
|
|
101
|
+
emailVerified: true,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
email: 'test@example.com',
|
|
105
|
+
name: 'Test User',
|
|
106
|
+
emailVerified: true,
|
|
107
|
+
},
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const result = await (db
|
|
112
|
+
.insert(users)
|
|
113
|
+
.values(sampleUsers)
|
|
114
|
+
.returning() as any)
|
|
115
|
+
console.log(`✓ Inserted ${result.length} users`)
|
|
116
|
+
console.log('✓ Database seeded successfully')
|
|
117
|
+
} catch (error: any) {
|
|
118
|
+
if (error?.message && error.message.includes('UNIQUE constraint failed')) {
|
|
119
|
+
console.log('✓ Seed data already exists, skipping...')
|
|
120
|
+
} else {
|
|
121
|
+
console.error('Error seeding database:', error)
|
|
122
|
+
throw error
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
seedDatabase().catch((error) => {
|
|
128
|
+
console.error('Seed script failed:', error)
|
|
129
|
+
process.exit(1)
|
|
130
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
namespace NodeJS {
|
|
3
|
+
interface ProcessEnv {
|
|
4
|
+
DATABASE_URL?: string
|
|
5
|
+
BETTER_AUTH_SECRET: string
|
|
6
|
+
BETTER_AUTH_URL?: string
|
|
7
|
+
BETTER_AUTH_EMAIL_PASSWORD?: string
|
|
8
|
+
RESEND_API_KEY: string
|
|
9
|
+
PUBLIC_APP_URL?: string
|
|
10
|
+
NODE_ENV: 'development' | 'test' | 'production'
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface ImportMetaEnv {
|
|
15
|
+
readonly DEV: boolean
|
|
16
|
+
readonly MODE: string
|
|
17
|
+
readonly BASE_URL: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface ImportMeta {
|
|
21
|
+
readonly env: ImportMetaEnv
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export {}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** @type {import('tailwindcss').Config} */
|
|
2
|
+
module.exports = {
|
|
3
|
+
darkMode: ['class'],
|
|
4
|
+
content: ['./src/**/*.{ts,tsx}'],
|
|
5
|
+
theme: {
|
|
6
|
+
extend: {
|
|
7
|
+
colors: {
|
|
8
|
+
border: 'hsl(var(--border))',
|
|
9
|
+
input: 'hsl(var(--input))',
|
|
10
|
+
ring: 'hsl(var(--ring))',
|
|
11
|
+
background: 'hsl(var(--background))',
|
|
12
|
+
foreground: 'hsl(var(--foreground))',
|
|
13
|
+
primary: {
|
|
14
|
+
DEFAULT: 'hsl(var(--primary))',
|
|
15
|
+
foreground: 'hsl(var(--primary-foreground))',
|
|
16
|
+
},
|
|
17
|
+
secondary: {
|
|
18
|
+
DEFAULT: 'hsl(var(--secondary))',
|
|
19
|
+
foreground: 'hsl(var(--secondary-foreground))',
|
|
20
|
+
},
|
|
21
|
+
destructive: {
|
|
22
|
+
DEFAULT: 'hsl(var(--destructive))',
|
|
23
|
+
foreground: 'hsl(var(--destructive-foreground))',
|
|
24
|
+
},
|
|
25
|
+
muted: {
|
|
26
|
+
DEFAULT: 'hsl(var(--muted))',
|
|
27
|
+
foreground: 'hsl(var(--muted-foreground))',
|
|
28
|
+
},
|
|
29
|
+
accent: {
|
|
30
|
+
DEFAULT: 'hsl(var(--accent))',
|
|
31
|
+
foreground: 'hsl(var(--accent-foreground))',
|
|
32
|
+
},
|
|
33
|
+
card: {
|
|
34
|
+
DEFAULT: 'hsl(var(--card))',
|
|
35
|
+
foreground: 'hsl(var(--card-foreground))',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
borderRadius: {
|
|
39
|
+
lg: 'var(--radius)',
|
|
40
|
+
md: 'calc(var(--radius) - 2px)',
|
|
41
|
+
sm: 'calc(var(--radius) - 4px)',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
plugins: [require('tailwindcss-animate')],
|
|
46
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
6
|
+
"jsx": "react-jsx",
|
|
7
|
+
"moduleResolution": "bundler",
|
|
8
|
+
"resolveJsonModule": true,
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
"checkJs": false,
|
|
11
|
+
"outDir": "./.vinxi/out",
|
|
12
|
+
"rootDir": "./src",
|
|
13
|
+
"removeComments": true,
|
|
14
|
+
"noEmit": true,
|
|
15
|
+
"importHelpers": true,
|
|
16
|
+
"downlevelIteration": true,
|
|
17
|
+
"isolatedModules": true,
|
|
18
|
+
"allowSyntheticDefaultImports": true,
|
|
19
|
+
"forceConsistentCasingInFileNames": true,
|
|
20
|
+
"strict": true,
|
|
21
|
+
"noUnusedLocals": true,
|
|
22
|
+
"noUnusedParameters": true,
|
|
23
|
+
"noImplicitReturns": true,
|
|
24
|
+
"noFallthroughCasesInSwitch": true,
|
|
25
|
+
"noUncheckedIndexedAccess": false,
|
|
26
|
+
"exactOptionalPropertyTypes": false,
|
|
27
|
+
"noImplicitOverride": true,
|
|
28
|
+
"esModuleInterop": true,
|
|
29
|
+
"skipLibCheck": true,
|
|
30
|
+
"paths": {
|
|
31
|
+
"@/*": ["./src/*"]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"include": ["src/**/*"],
|
|
35
|
+
"exclude": ["node_modules", "dist", ".vinxi"]
|
|
36
|
+
}
|