@bash-app/bash-common 30.97.0 → 30.97.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.
@@ -0,0 +1,198 @@
1
+ # Database Migration Checklist
2
+
3
+ ## Problem
4
+ - ❌ Error: `The column Service.acceptsBashCash does not exist in the current database`
5
+ - ❌ Error: `https://api.bash.community/api/public-services/Sponsors` returning 500
6
+
7
+ ## Root Cause
8
+ Prisma schema was updated but database wasn't migrated. The code expects columns/tables that don't exist yet.
9
+
10
+ ---
11
+
12
+ ## Missing From Database
13
+
14
+ 1. ❌ `Service.acceptsBashCash` (column)
15
+ 2. ❌ `User.isLightweightAccount` (column)
16
+ 3. ❌ `TaskComment` (entire table)
17
+ 4. ❌ `TaskInvitation` (entire table)
18
+
19
+ ---
20
+
21
+ ## Fix Steps
22
+
23
+ ### ✅ Step 1: Apply Migration
24
+
25
+ **Choose ONE method:**
26
+
27
+ #### Option A: Vercel Dashboard (Recommended - Easiest)
28
+ ```
29
+ 1. Go to: https://vercel.com/dashboard
30
+ 2. Navigate to: Your Project > Storage > Postgres
31
+ 3. Click: "Query" tab
32
+ 4. Copy contents of: bash-common/prisma/quick-migration.sql
33
+ 5. Paste and execute
34
+ ```
35
+
36
+ #### Option B: Prisma CLI (Recommended - Safest)
37
+ ```bash
38
+ cd bash-common
39
+ npx prisma db push
40
+ ```
41
+
42
+ #### Option C: Command Line
43
+ ```bash
44
+ psql $DATABASE_URL -f bash-common/prisma/quick-migration.sql
45
+ ```
46
+
47
+ ### ✅ Step 2: Verify Migration
48
+
49
+ Check that migration worked:
50
+
51
+ ```sql
52
+ -- In your database query tool:
53
+
54
+ -- 1. Check Service.acceptsBashCash exists
55
+ SELECT column_name FROM information_schema.columns
56
+ WHERE table_name = 'Service' AND column_name = 'acceptsBashCash';
57
+ -- Expected: Returns 1 row
58
+
59
+ -- 2. Check User.isLightweightAccount exists
60
+ SELECT column_name FROM information_schema.columns
61
+ WHERE table_name = 'User' AND column_name = 'isLightweightAccount';
62
+ -- Expected: Returns 1 row
63
+
64
+ -- 3. Check TaskComment table exists
65
+ SELECT table_name FROM information_schema.tables
66
+ WHERE table_name = 'TaskComment';
67
+ -- Expected: Returns 1 row
68
+
69
+ -- 4. Check TaskInvitation table exists
70
+ SELECT table_name FROM information_schema.tables
71
+ WHERE table_name = 'TaskInvitation';
72
+ -- Expected: Returns 1 row
73
+ ```
74
+
75
+ ### ✅ Step 3: Restart API
76
+
77
+ If using Vercel:
78
+ - Should auto-restart within 30 seconds
79
+ - Monitor: https://vercel.com/dashboard > Deployments
80
+
81
+ If self-hosted:
82
+ ```bash
83
+ # Restart your API process
84
+ pm2 restart api
85
+ # or
86
+ systemctl restart bash-api
87
+ # or however you restart your API
88
+ ```
89
+
90
+ ### ✅ Step 4: Test
91
+
92
+ 1. Test the failing endpoint:
93
+ ```bash
94
+ curl https://api.bash.community/api/public-services/Sponsors
95
+ ```
96
+ Expected: 200 OK (not 500 error)
97
+
98
+ 2. Check frontend:
99
+ - Reload https://bash.community
100
+ - Navigate to sponsors page
101
+ - Should load without errors
102
+
103
+ 3. Test task system:
104
+ - Create an event
105
+ - Add a task
106
+ - Try commenting on it
107
+ - Try sending invitation
108
+
109
+ ### ✅ Step 5: Clear Caches (if applicable)
110
+
111
+ ```bash
112
+ # If using Redis
113
+ redis-cli FLUSHALL
114
+
115
+ # If using CDN/Cloudflare
116
+ # Purge cache in their dashboard
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Prevention for Next Time
122
+
123
+ ### Proper Workflow:
124
+
125
+ 1. **Update Schema**
126
+ ```bash
127
+ # Edit bash-common/prisma/schema.prisma
128
+ ```
129
+
130
+ 2. **Generate Client**
131
+ ```bash
132
+ cd bash-common
133
+ npx prisma generate
134
+ ```
135
+
136
+ 3. **Push to Database** ⚠️ (You skipped this!)
137
+ ```bash
138
+ npx prisma db push
139
+ # OR for production with proper migrations:
140
+ npx prisma migrate dev --name your_change_name
141
+ npx prisma migrate deploy
142
+ ```
143
+
144
+ 4. **Build & Deploy**
145
+ ```bash
146
+ npm run build
147
+ # Deploy to production
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Files Created
153
+
154
+ - ✅ `bash-common/prisma/quick-migration.sql` - Quick fix (50 lines)
155
+ - ✅ `bash-common/prisma/manual-migration-add-missing-columns.sql` - Detailed (250 lines)
156
+ - ✅ `bash-common/prisma/MIGRATION-CHECKLIST.md` - This file
157
+
158
+ ---
159
+
160
+ ## Rollback (Emergency Only)
161
+
162
+ If something goes wrong, rollback:
163
+
164
+ ```sql
165
+ -- WARNING: This will delete data!
166
+ ALTER TABLE "Service" DROP COLUMN IF EXISTS "acceptsBashCash";
167
+ ALTER TABLE "User" DROP COLUMN IF EXISTS "isLightweightAccount";
168
+ DROP TABLE IF EXISTS "TaskComment" CASCADE;
169
+ DROP TABLE IF EXISTS "TaskInvitation" CASCADE;
170
+ ```
171
+
172
+ Then restore from backup.
173
+
174
+ ---
175
+
176
+ ## Status
177
+
178
+ - [ ] Migration applied
179
+ - [ ] Database verified
180
+ - [ ] API restarted
181
+ - [ ] Tests passed
182
+ - [ ] Caches cleared
183
+ - [ ] Production working
184
+
185
+ ---
186
+
187
+ ## Support
188
+
189
+ If issues persist:
190
+ 1. Check Vercel logs: https://vercel.com/dashboard > Your Project > Logs
191
+ 2. Check database connectivity
192
+ 3. Verify Prisma client was regenerated
193
+ 4. Check for other missing columns using:
194
+ ```bash
195
+ npx prisma db pull
196
+ # Compare with your schema.prisma
197
+ ```
198
+
@@ -0,0 +1,182 @@
1
+ -- ============================================================================
2
+ -- BASH DATABASE MIGRATION - Missing Columns
3
+ -- Date: November 14, 2025
4
+ -- Description: Add missing columns from Prisma schema to production database
5
+ -- ============================================================================
6
+
7
+ -- Issue: Prisma schema has been updated but migrations weren't run
8
+ -- This SQL adds all missing columns that are causing runtime errors
9
+
10
+ -- ============================================================================
11
+ -- 1. Service Table - Add acceptsBashCash column
12
+ -- ============================================================================
13
+ -- This column controls whether a service accepts BashCash payments
14
+ -- Default: true (most services should accept BashCash)
15
+
16
+ ALTER TABLE "Service"
17
+ ADD COLUMN IF NOT EXISTS "acceptsBashCash" BOOLEAN NOT NULL DEFAULT true;
18
+
19
+ COMMENT ON COLUMN "Service"."acceptsBashCash" IS 'Whether this service accepts BashCash as payment';
20
+
21
+ -- ============================================================================
22
+ -- 2. User Table - Add isLightweightAccount column
23
+ -- ============================================================================
24
+ -- This column marks accounts created automatically via task invitation acceptance
25
+ -- These accounts need password changes and may have limited permissions initially
26
+
27
+ ALTER TABLE "User"
28
+ ADD COLUMN IF NOT EXISTS "isLightweightAccount" BOOLEAN NOT NULL DEFAULT false;
29
+
30
+ COMMENT ON COLUMN "User"."isLightweightAccount" IS 'True if account was auto-created via task invitation (needs password change)';
31
+
32
+ -- ============================================================================
33
+ -- 3. TaskComment Table - Create if not exists
34
+ -- ============================================================================
35
+ -- This table stores comments on event tasks
36
+ -- Used for host-volunteer communication about task details
37
+
38
+ CREATE TABLE IF NOT EXISTS "TaskComment" (
39
+ "id" TEXT NOT NULL PRIMARY KEY,
40
+ "taskId" TEXT NOT NULL,
41
+ "authorId" TEXT NOT NULL,
42
+ "content" TEXT NOT NULL,
43
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
44
+ CONSTRAINT "TaskComment_taskId_fkey" FOREIGN KEY ("taskId") REFERENCES "EventTask"("id") ON DELETE CASCADE ON UPDATE CASCADE,
45
+ CONSTRAINT "TaskComment_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE
46
+ );
47
+
48
+ -- Create indexes for TaskComment
49
+ CREATE INDEX IF NOT EXISTS "TaskComment_taskId_idx" ON "TaskComment"("taskId");
50
+ CREATE INDEX IF NOT EXISTS "TaskComment_authorId_idx" ON "TaskComment"("authorId");
51
+ CREATE INDEX IF NOT EXISTS "TaskComment_createdAt_idx" ON "TaskComment"("createdAt");
52
+
53
+ COMMENT ON TABLE "TaskComment" IS 'Comments on event tasks for host-volunteer communication';
54
+
55
+ -- ============================================================================
56
+ -- 4. TaskInvitation Table - Create if not exists
57
+ -- ============================================================================
58
+ -- This table stores email invitations for non-users to accept event tasks
59
+ -- When accepted, creates lightweight user accounts automatically
60
+
61
+ CREATE TABLE IF NOT EXISTS "TaskInvitation" (
62
+ "id" TEXT NOT NULL PRIMARY KEY,
63
+ "taskId" TEXT NOT NULL,
64
+ "invitedEmail" TEXT NOT NULL,
65
+ "token" TEXT NOT NULL UNIQUE,
66
+ "invitedName" TEXT,
67
+ "personalMessage" TEXT,
68
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
69
+ "expiresAt" TIMESTAMP(3) NOT NULL,
70
+ "acceptedAt" TIMESTAMP(3),
71
+ "acceptedById" TEXT,
72
+ "createdById" TEXT NOT NULL,
73
+ CONSTRAINT "TaskInvitation_taskId_fkey" FOREIGN KEY ("taskId") REFERENCES "EventTask"("id") ON DELETE CASCADE ON UPDATE CASCADE,
74
+ CONSTRAINT "TaskInvitation_acceptedById_fkey" FOREIGN KEY ("acceptedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE,
75
+ CONSTRAINT "TaskInvitation_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE
76
+ );
77
+
78
+ -- Create indexes for TaskInvitation
79
+ CREATE INDEX IF NOT EXISTS "TaskInvitation_token_idx" ON "TaskInvitation"("token");
80
+ CREATE INDEX IF NOT EXISTS "TaskInvitation_invitedEmail_idx" ON "TaskInvitation"("invitedEmail");
81
+ CREATE INDEX IF NOT EXISTS "TaskInvitation_taskId_idx" ON "TaskInvitation"("taskId");
82
+ CREATE INDEX IF NOT EXISTS "TaskInvitation_createdById_idx" ON "TaskInvitation"("createdById");
83
+ CREATE INDEX IF NOT EXISTS "TaskInvitation_acceptedById_idx" ON "TaskInvitation"("acceptedById");
84
+
85
+ COMMENT ON TABLE "TaskInvitation" IS 'Email invitations for non-users to accept event tasks';
86
+ COMMENT ON COLUMN "TaskInvitation"."token" IS 'Unique CUID token for invitation link';
87
+ COMMENT ON COLUMN "TaskInvitation"."invitedName" IS 'Optional name hint from host';
88
+ COMMENT ON COLUMN "TaskInvitation"."personalMessage" IS 'Optional personal message from host';
89
+ COMMENT ON COLUMN "TaskInvitation"."expiresAt" IS 'Event date + 1 day';
90
+
91
+ -- ============================================================================
92
+ -- 5. Update User Table - Add missing task-related relations
93
+ -- ============================================================================
94
+ -- These columns should already exist if EventTask table exists, but verify:
95
+
96
+ -- Check if comments column is needed (it's a relation, not a physical column)
97
+ -- Check if invitations columns are needed (they're relations, not physical columns)
98
+
99
+ -- ============================================================================
100
+ -- 6. Verification Queries
101
+ -- ============================================================================
102
+ -- Run these to verify the migration was successful:
103
+
104
+ -- Check Service table
105
+ -- SELECT column_name, data_type, column_default
106
+ -- FROM information_schema.columns
107
+ -- WHERE table_name = 'Service' AND column_name = 'acceptsBashCash';
108
+
109
+ -- Check User table
110
+ -- SELECT column_name, data_type, column_default
111
+ -- FROM information_schema.columns
112
+ -- WHERE table_name = 'User' AND column_name = 'isLightweightAccount';
113
+
114
+ -- Check TaskComment table exists
115
+ -- SELECT table_name FROM information_schema.tables WHERE table_name = 'TaskComment';
116
+
117
+ -- Check TaskInvitation table exists
118
+ -- SELECT table_name FROM information_schema.tables WHERE table_name = 'TaskInvitation';
119
+
120
+ -- ============================================================================
121
+ -- 7. Rollback (if needed)
122
+ -- ============================================================================
123
+ -- DO NOT RUN UNLESS ROLLING BACK!
124
+
125
+ -- -- Remove acceptsBashCash
126
+ -- ALTER TABLE "Service" DROP COLUMN IF EXISTS "acceptsBashCash";
127
+
128
+ -- -- Remove isLightweightAccount
129
+ -- ALTER TABLE "User" DROP COLUMN IF EXISTS "isLightweightAccount";
130
+
131
+ -- -- Drop TaskComment table
132
+ -- DROP TABLE IF EXISTS "TaskComment" CASCADE;
133
+
134
+ -- -- Drop TaskInvitation table
135
+ -- DROP TABLE IF EXISTS "TaskInvitation" CASCADE;
136
+
137
+ -- ============================================================================
138
+ -- 8. Post-Migration Tasks
139
+ -- ============================================================================
140
+ -- After running this migration:
141
+ -- 1. Restart API server
142
+ -- 2. Clear any Redis/cache
143
+ -- 3. Run `npx prisma generate` in bash-common
144
+ -- 4. Test the /api/public-services/Sponsors endpoint
145
+ -- 5. Test task invitation flow
146
+ -- 6. Test task comment system
147
+
148
+ -- ============================================================================
149
+ -- EXECUTION INSTRUCTIONS
150
+ -- ============================================================================
151
+ --
152
+ -- To apply this migration to your PostgreSQL database:
153
+ --
154
+ -- Option 1: Using psql command line
155
+ -- $ psql -U your_username -d your_database -f add_missing_columns.sql
156
+ --
157
+ -- Option 2: Using Prisma
158
+ -- $ cd bash-common
159
+ -- $ npx prisma db push
160
+ --
161
+ -- Option 3: Copy-paste into Vercel Postgres Dashboard
162
+ -- 1. Go to Vercel Dashboard > Storage > Your Postgres DB > Query
163
+ -- 2. Copy-paste the SQL statements (exclude comments if needed)
164
+ -- 3. Execute
165
+ --
166
+ -- Option 4: Using TablePlus or another GUI
167
+ -- 1. Connect to your database
168
+ -- 2. Open SQL query window
169
+ -- 3. Copy-paste and execute
170
+ --
171
+ -- ============================================================================
172
+ -- IMPORTANT NOTES
173
+ -- ============================================================================
174
+ --
175
+ -- 1. This migration is IDEMPOTENT - safe to run multiple times
176
+ -- 2. Uses "IF NOT EXISTS" to prevent errors on re-run
177
+ -- 3. All new columns have DEFAULT values to avoid breaking existing data
178
+ -- 4. Foreign keys use CASCADE for proper cleanup
179
+ -- 5. Indexes are created for query performance
180
+ --
181
+ -- ============================================================================
182
+
@@ -0,0 +1,47 @@
1
+ -- Quick Migration SQL - Copy and paste into Vercel Postgres Query
2
+ -- Adds missing columns that are causing errors
3
+
4
+ -- 1. Add acceptsBashCash to Service table
5
+ ALTER TABLE "Service" ADD COLUMN IF NOT EXISTS "acceptsBashCash" BOOLEAN NOT NULL DEFAULT true;
6
+
7
+ -- 2. Add isLightweightAccount to User table
8
+ ALTER TABLE "User" ADD COLUMN IF NOT EXISTS "isLightweightAccount" BOOLEAN NOT NULL DEFAULT false;
9
+
10
+ -- 3. Create TaskComment table
11
+ CREATE TABLE IF NOT EXISTS "TaskComment" (
12
+ "id" TEXT NOT NULL PRIMARY KEY,
13
+ "taskId" TEXT NOT NULL,
14
+ "authorId" TEXT NOT NULL,
15
+ "content" TEXT NOT NULL,
16
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
17
+ CONSTRAINT "TaskComment_taskId_fkey" FOREIGN KEY ("taskId") REFERENCES "EventTask"("id") ON DELETE CASCADE,
18
+ CONSTRAINT "TaskComment_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE CASCADE
19
+ );
20
+
21
+ CREATE INDEX IF NOT EXISTS "TaskComment_taskId_idx" ON "TaskComment"("taskId");
22
+ CREATE INDEX IF NOT EXISTS "TaskComment_authorId_idx" ON "TaskComment"("authorId");
23
+
24
+ -- 4. Create TaskInvitation table
25
+ CREATE TABLE IF NOT EXISTS "TaskInvitation" (
26
+ "id" TEXT NOT NULL PRIMARY KEY,
27
+ "taskId" TEXT NOT NULL,
28
+ "invitedEmail" TEXT NOT NULL,
29
+ "token" TEXT NOT NULL UNIQUE,
30
+ "invitedName" TEXT,
31
+ "personalMessage" TEXT,
32
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
33
+ "expiresAt" TIMESTAMP(3) NOT NULL,
34
+ "acceptedAt" TIMESTAMP(3),
35
+ "acceptedById" TEXT,
36
+ "createdById" TEXT NOT NULL,
37
+ CONSTRAINT "TaskInvitation_taskId_fkey" FOREIGN KEY ("taskId") REFERENCES "EventTask"("id") ON DELETE CASCADE,
38
+ CONSTRAINT "TaskInvitation_acceptedById_fkey" FOREIGN KEY ("acceptedById") REFERENCES "User"("id") ON DELETE SET NULL,
39
+ CONSTRAINT "TaskInvitation_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE CASCADE
40
+ );
41
+
42
+ CREATE INDEX IF NOT EXISTS "TaskInvitation_token_idx" ON "TaskInvitation"("token");
43
+ CREATE INDEX IF NOT EXISTS "TaskInvitation_invitedEmail_idx" ON "TaskInvitation"("invitedEmail");
44
+ CREATE INDEX IF NOT EXISTS "TaskInvitation_taskId_idx" ON "TaskInvitation"("taskId");
45
+
46
+ -- Done! Restart your API server after running this.
47
+