@bash-app/bash-common 30.97.0 → 30.98.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.
- package/dist/definitions.d.ts +2 -2
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +2 -2
- package/dist/definitions.js.map +1 -1
- package/dist/extendedSchemas.d.ts +176 -1
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js +11 -0
- package/dist/extendedSchemas.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/index.d.ts +42 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +43 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/venueTypeFormatter.d.ts +10 -0
- package/dist/utils/venueTypeFormatter.d.ts.map +1 -0
- package/dist/utils/venueTypeFormatter.js +25 -0
- package/dist/utils/venueTypeFormatter.js.map +1 -0
- package/package.json +1 -1
- package/prisma/MIGRATION-CHECKLIST.md +198 -0
- package/prisma/manual-migration-add-missing-columns.sql +182 -0
- package/prisma/quick-migration.sql +47 -0
- package/prisma/schema.prisma +262 -63
- package/src/definitions.ts +3 -1
- package/src/extendedSchemas.ts +22 -0
- package/src/index.ts +1 -0
- package/src/utils/contentFilterUtils.ts +1 -0
- package/src/utils/index.ts +43 -0
- package/src/utils/venueTypeFormatter.ts +30 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export * from './addressUtils';
|
|
2
|
+
export * from './apiUtils';
|
|
3
|
+
export * from './arrayUtils';
|
|
4
|
+
export * from './awsS3Utils';
|
|
5
|
+
export * from './badgeUtils';
|
|
6
|
+
export * from './bashCashPaymentUtils';
|
|
7
|
+
export * from './blog/blogDbUtils';
|
|
8
|
+
export * from './blogUtils';
|
|
9
|
+
export * from './contentFilterUtils';
|
|
10
|
+
export * from './dateTimeUtils';
|
|
11
|
+
export * from './entityUtils';
|
|
12
|
+
export * from './generalDateTimeUtils';
|
|
13
|
+
export * from './luxonUtils';
|
|
14
|
+
export * from './mathUtils';
|
|
15
|
+
export * from './objUtils';
|
|
16
|
+
export * from './paymentUtils';
|
|
17
|
+
export * from './promoCodesUtils';
|
|
18
|
+
export * from './qrCodeUtils';
|
|
19
|
+
export * from './recurrenceUtils';
|
|
20
|
+
export * from './reviewUtils';
|
|
21
|
+
export * from './service/apiServiceBookingApiUtils';
|
|
22
|
+
export * from './service/attendeeOptionUtils';
|
|
23
|
+
export * from './service/frontendServiceBookingUtils';
|
|
24
|
+
export * from './service/regexUtils';
|
|
25
|
+
export * from './service/serviceBookingStatusUtils';
|
|
26
|
+
export * from './service/serviceBookingTypes';
|
|
27
|
+
export * from './service/serviceDBUtils';
|
|
28
|
+
export * from './service/serviceRateTypes';
|
|
29
|
+
export * from './service/serviceRateUtils';
|
|
30
|
+
export * from './service/serviceUtils';
|
|
31
|
+
export * from './slugUtils';
|
|
32
|
+
export * from './sortUtils';
|
|
33
|
+
export * from './stringUtils';
|
|
34
|
+
export * from './stripeAccountUtils';
|
|
35
|
+
export * from './ticketListUtils';
|
|
36
|
+
export * from './typeUtils';
|
|
37
|
+
export * from './urlUtils';
|
|
38
|
+
export * from './userPromoCodeUtils';
|
|
39
|
+
export * from './userSubscriptionUtils';
|
|
40
|
+
export * from './userUtils';
|
|
41
|
+
export * from './venueTypeFormatter';
|
|
42
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uCAAuC,CAAC;AACtD,cAAc,sBAAsB,CAAC;AACrC,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AAEzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export * from './addressUtils';
|
|
2
|
+
export * from './apiUtils';
|
|
3
|
+
export * from './arrayUtils';
|
|
4
|
+
export * from './awsS3Utils';
|
|
5
|
+
export * from './badgeUtils';
|
|
6
|
+
export * from './bashCashPaymentUtils';
|
|
7
|
+
export * from './blog/blogDbUtils';
|
|
8
|
+
export * from './blogUtils';
|
|
9
|
+
export * from './contentFilterUtils';
|
|
10
|
+
export * from './dateTimeUtils';
|
|
11
|
+
export * from './entityUtils';
|
|
12
|
+
export * from './generalDateTimeUtils';
|
|
13
|
+
export * from './luxonUtils';
|
|
14
|
+
export * from './mathUtils';
|
|
15
|
+
export * from './objUtils';
|
|
16
|
+
export * from './paymentUtils';
|
|
17
|
+
export * from './promoCodesUtils';
|
|
18
|
+
export * from './qrCodeUtils';
|
|
19
|
+
export * from './recurrenceUtils';
|
|
20
|
+
export * from './reviewUtils';
|
|
21
|
+
export * from './service/apiServiceBookingApiUtils';
|
|
22
|
+
export * from './service/attendeeOptionUtils';
|
|
23
|
+
export * from './service/frontendServiceBookingUtils';
|
|
24
|
+
export * from './service/regexUtils';
|
|
25
|
+
export * from './service/serviceBookingStatusUtils';
|
|
26
|
+
export * from './service/serviceBookingTypes';
|
|
27
|
+
export * from './service/serviceDBUtils';
|
|
28
|
+
// export * from './service/serviceRateDBUtils'; // File is all commented out
|
|
29
|
+
export * from './service/serviceRateTypes';
|
|
30
|
+
export * from './service/serviceRateUtils';
|
|
31
|
+
export * from './service/serviceUtils';
|
|
32
|
+
export * from './slugUtils';
|
|
33
|
+
export * from './sortUtils';
|
|
34
|
+
export * from './stringUtils';
|
|
35
|
+
export * from './stripeAccountUtils';
|
|
36
|
+
export * from './ticketListUtils';
|
|
37
|
+
export * from './typeUtils';
|
|
38
|
+
export * from './urlUtils';
|
|
39
|
+
export * from './userPromoCodeUtils';
|
|
40
|
+
export * from './userSubscriptionUtils';
|
|
41
|
+
export * from './userUtils';
|
|
42
|
+
export * from './venueTypeFormatter';
|
|
43
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uCAAuC,CAAC;AACtD,cAAc,sBAAsB,CAAC;AACrC,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,6EAA6E;AAC7E,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats venue type enum values into human-readable display names
|
|
3
|
+
* Example: "OutdoorSpace" -> "Outdoor Space", "WeddingVenue" -> "Wedding Venue"
|
|
4
|
+
*/
|
|
5
|
+
export declare function formatVenueType(venueType: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Formats an array of venue types into a human-readable string
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatVenueTypes(venueTypes: string[], maxDisplay?: number): string;
|
|
10
|
+
//# sourceMappingURL=venueTypeFormatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"venueTypeFormatter.d.ts","sourceRoot":"","sources":["../../src/utils/venueTypeFormatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,UAAU,GAAE,MAAU,GAAG,MAAM,CAarF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats venue type enum values into human-readable display names
|
|
3
|
+
* Example: "OutdoorSpace" -> "Outdoor Space", "WeddingVenue" -> "Wedding Venue"
|
|
4
|
+
*/
|
|
5
|
+
export function formatVenueType(venueType) {
|
|
6
|
+
if (!venueType)
|
|
7
|
+
return '';
|
|
8
|
+
// Insert space before capital letters (but not at the start)
|
|
9
|
+
return venueType.replace(/([A-Z])/g, ' $1').trim();
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Formats an array of venue types into a human-readable string
|
|
13
|
+
*/
|
|
14
|
+
export function formatVenueTypes(venueTypes, maxDisplay = 2) {
|
|
15
|
+
if (!Array.isArray(venueTypes) || venueTypes.length === 0) {
|
|
16
|
+
return '';
|
|
17
|
+
}
|
|
18
|
+
const formatted = venueTypes.slice(0, maxDisplay).map(formatVenueType);
|
|
19
|
+
const remaining = venueTypes.length - maxDisplay;
|
|
20
|
+
if (remaining > 0) {
|
|
21
|
+
return `${formatted.join(', ')} +${remaining} more`;
|
|
22
|
+
}
|
|
23
|
+
return formatted.join(', ');
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=venueTypeFormatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"venueTypeFormatter.js","sourceRoot":"","sources":["../../src/utils/venueTypeFormatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,CAAC;IAE1B,6DAA6D;IAC7D,OAAO,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAoB,EAAE,aAAqB,CAAC;IAC3E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1D,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACvE,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,GAAG,UAAU,CAAC;IAEjD,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QAClB,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,SAAS,OAAO,CAAC;IACtD,CAAC;IAED,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC"}
|
package/package.json
CHANGED
|
@@ -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
|
+
|