@bash-app/bash-common 30.432.0 → 30.434.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/__tests__/appleIapProducts.test.js +1 -0
- package/dist/__tests__/appleIapProducts.test.js.map +1 -1
- package/dist/__tests__/bashSectionTitleForBashType.test.js +2 -0
- package/dist/__tests__/bashSectionTitleForBashType.test.js.map +1 -1
- package/dist/__tests__/discoveryScope.test.js +9 -1
- package/dist/__tests__/discoveryScope.test.js.map +1 -1
- package/dist/__tests__/promoCartEngine.test.d.ts +2 -0
- package/dist/__tests__/promoCartEngine.test.d.ts.map +1 -0
- package/dist/__tests__/promoCartEngine.test.js +174 -0
- package/dist/__tests__/promoCartEngine.test.js.map +1 -0
- package/dist/__tests__/promoCodeRedemption.test.d.ts +2 -0
- package/dist/__tests__/promoCodeRedemption.test.d.ts.map +1 -0
- package/dist/__tests__/promoCodeRedemption.test.js +103 -0
- package/dist/__tests__/promoCodeRedemption.test.js.map +1 -0
- package/dist/__tests__/promoCodeScope.test.d.ts +2 -0
- package/dist/__tests__/promoCodeScope.test.d.ts.map +1 -0
- package/dist/__tests__/promoCodeScope.test.js +84 -0
- package/dist/__tests__/promoCodeScope.test.js.map +1 -0
- package/dist/__tests__/statusEnums.test.js +1 -0
- package/dist/__tests__/statusEnums.test.js.map +1 -1
- package/dist/appleIapProducts.d.ts +12 -2
- package/dist/appleIapProducts.d.ts.map +1 -1
- package/dist/appleIapProducts.js +13 -0
- package/dist/appleIapProducts.js.map +1 -1
- package/dist/definitions.d.ts +3 -1
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +4 -2
- package/dist/definitions.js.map +1 -1
- package/dist/discoveryScope.d.ts +6 -6
- package/dist/discoveryScope.d.ts.map +1 -1
- package/dist/discoveryScope.js +25 -16
- package/dist/discoveryScope.js.map +1 -1
- package/dist/extendedSchemas.d.ts +1 -0
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/intros/__tests__/introsReleaseGates.test.d.ts +2 -0
- package/dist/intros/__tests__/introsReleaseGates.test.d.ts.map +1 -0
- package/dist/intros/__tests__/introsReleaseGates.test.js +140 -0
- package/dist/intros/__tests__/introsReleaseGates.test.js.map +1 -0
- package/dist/intros/__tests__/psychExperiment.test.d.ts +2 -0
- package/dist/intros/__tests__/psychExperiment.test.d.ts.map +1 -0
- package/dist/intros/__tests__/psychExperiment.test.js +63 -0
- package/dist/intros/__tests__/psychExperiment.test.js.map +1 -0
- package/dist/intros/__tests__/reasons.test.d.ts +2 -0
- package/dist/intros/__tests__/reasons.test.d.ts.map +1 -0
- package/dist/intros/__tests__/reasons.test.js +72 -0
- package/dist/intros/__tests__/reasons.test.js.map +1 -0
- package/dist/intros/__tests__/sharedNotes.test.d.ts +2 -0
- package/dist/intros/__tests__/sharedNotes.test.d.ts.map +1 -0
- package/dist/intros/__tests__/sharedNotes.test.js +19 -0
- package/dist/intros/__tests__/sharedNotes.test.js.map +1 -0
- package/dist/intros/__tests__/transitions.test.d.ts +2 -0
- package/dist/intros/__tests__/transitions.test.d.ts.map +1 -0
- package/dist/intros/__tests__/transitions.test.js +43 -0
- package/dist/intros/__tests__/transitions.test.js.map +1 -0
- package/dist/intros/__tests__/warmDisclosure.test.d.ts +2 -0
- package/dist/intros/__tests__/warmDisclosure.test.d.ts.map +1 -0
- package/dist/intros/__tests__/warmDisclosure.test.js +10 -0
- package/dist/intros/__tests__/warmDisclosure.test.js.map +1 -0
- package/dist/intros/age.d.ts +4 -0
- package/dist/intros/age.d.ts.map +1 -0
- package/dist/intros/age.js +14 -0
- package/dist/intros/age.js.map +1 -0
- package/dist/intros/attendance.d.ts +11 -0
- package/dist/intros/attendance.d.ts.map +1 -0
- package/dist/intros/attendance.js +27 -0
- package/dist/intros/attendance.js.map +1 -0
- package/dist/intros/attributeCatalog.d.ts +17 -0
- package/dist/intros/attributeCatalog.d.ts.map +1 -0
- package/dist/intros/attributeCatalog.js +96 -0
- package/dist/intros/attributeCatalog.js.map +1 -0
- package/dist/intros/index.d.ts +10 -0
- package/dist/intros/index.d.ts.map +1 -0
- package/dist/intros/index.js +10 -0
- package/dist/intros/index.js.map +1 -0
- package/dist/intros/intents.d.ts +8 -0
- package/dist/intros/intents.d.ts.map +1 -0
- package/dist/intros/intents.js +44 -0
- package/dist/intros/intents.js.map +1 -0
- package/dist/intros/psychExperiment.d.ts +29 -0
- package/dist/intros/psychExperiment.d.ts.map +1 -0
- package/dist/intros/psychExperiment.js +82 -0
- package/dist/intros/psychExperiment.js.map +1 -0
- package/dist/intros/reasons.d.ts +38 -0
- package/dist/intros/reasons.d.ts.map +1 -0
- package/dist/intros/reasons.js +162 -0
- package/dist/intros/reasons.js.map +1 -0
- package/dist/intros/sharedNotes.d.ts +10 -0
- package/dist/intros/sharedNotes.d.ts.map +1 -0
- package/dist/intros/sharedNotes.js +56 -0
- package/dist/intros/sharedNotes.js.map +1 -0
- package/dist/intros/transitions.d.ts +29 -0
- package/dist/intros/transitions.d.ts.map +1 -0
- package/dist/intros/transitions.js +128 -0
- package/dist/intros/transitions.js.map +1 -0
- package/dist/intros/validation.d.ts +50 -0
- package/dist/intros/validation.d.ts.map +1 -0
- package/dist/intros/validation.js +212 -0
- package/dist/intros/validation.js.map +1 -0
- package/dist/mirroredPrismaEnums.d.ts +1 -0
- package/dist/mirroredPrismaEnums.d.ts.map +1 -1
- package/dist/mirroredPrismaEnums.js +1 -0
- package/dist/mirroredPrismaEnums.js.map +1 -1
- package/dist/promoCartEngine.d.ts +55 -0
- package/dist/promoCartEngine.d.ts.map +1 -0
- package/dist/promoCartEngine.js +135 -0
- package/dist/promoCartEngine.js.map +1 -0
- package/dist/promoCodeRedemption.d.ts +44 -0
- package/dist/promoCodeRedemption.d.ts.map +1 -0
- package/dist/promoCodeRedemption.js +81 -0
- package/dist/promoCodeRedemption.js.map +1 -0
- package/dist/promoCodeScope.d.ts +91 -0
- package/dist/promoCodeScope.d.ts.map +1 -0
- package/dist/promoCodeScope.js +102 -0
- package/dist/promoCodeScope.js.map +1 -0
- package/dist/utils/__tests__/discountEngine/discountCalculator.test.js +8 -1
- package/dist/utils/__tests__/discountEngine/discountCalculator.test.js.map +1 -1
- package/dist/utils/__tests__/paymentUtils.test.js +87 -4
- package/dist/utils/__tests__/paymentUtils.test.js.map +1 -1
- package/dist/utils/paymentUtils.d.ts +30 -5
- package/dist/utils/paymentUtils.d.ts.map +1 -1
- package/dist/utils/paymentUtils.js +43 -11
- package/dist/utils/paymentUtils.js.map +1 -1
- package/package.json +1 -1
- package/prisma/schema.prisma +427 -6
- package/src/__tests__/appleIapProducts.test.ts +3 -0
- package/src/__tests__/bashSectionTitleForBashType.test.ts +4 -0
- package/src/__tests__/discoveryScope.test.ts +22 -1
- package/src/__tests__/promoCartEngine.test.ts +201 -0
- package/src/__tests__/promoCodeRedemption.test.ts +134 -0
- package/src/__tests__/promoCodeScope.test.ts +119 -0
- package/src/__tests__/statusEnums.test.ts +1 -0
- package/src/appleIapProducts.ts +29 -2
- package/src/definitions.ts +4 -2
- package/src/discoveryScope.ts +30 -20
- package/src/extendedSchemas.ts +1 -0
- package/src/index.ts +4 -0
- package/src/intros/__tests__/introsReleaseGates.test.ts +181 -0
- package/src/intros/__tests__/psychExperiment.test.ts +99 -0
- package/src/intros/__tests__/reasons.test.ts +122 -0
- package/src/intros/__tests__/sharedNotes.test.ts +20 -0
- package/src/intros/__tests__/transitions.test.ts +61 -0
- package/src/intros/__tests__/warmDisclosure.test.ts +10 -0
- package/src/intros/age.ts +13 -0
- package/src/intros/attendance.ts +33 -0
- package/src/intros/attributeCatalog.ts +113 -0
- package/src/intros/index.ts +9 -0
- package/src/intros/intents.ts +49 -0
- package/src/intros/psychExperiment.ts +130 -0
- package/src/intros/reasons.ts +187 -0
- package/src/intros/sharedNotes.ts +59 -0
- package/src/intros/transitions.ts +172 -0
- package/src/intros/validation.ts +248 -0
- package/src/mirroredPrismaEnums.ts +1 -0
- package/src/promoCartEngine.ts +193 -0
- package/src/promoCodeRedemption.ts +123 -0
- package/src/promoCodeScope.ts +180 -0
- package/src/utils/__tests__/discountEngine/discountCalculator.test.ts +8 -0
- package/src/utils/__tests__/paymentUtils.test.ts +100 -6
- package/src/utils/paymentUtils.ts +56 -13
package/prisma/schema.prisma
CHANGED
|
@@ -633,7 +633,19 @@ model SentReminder {
|
|
|
633
633
|
model BashEventPromoCode {
|
|
634
634
|
id String @id @default(cuid())
|
|
635
635
|
code String
|
|
636
|
-
|
|
636
|
+
/// Legacy single tier. Null for bash-level codes; eligibility lives in eligibilityMode + eligibleTiers.
|
|
637
|
+
ticketTierId String?
|
|
638
|
+
/// Owning bash. Backfilled from the tier for legacy rows.
|
|
639
|
+
bashEventId String?
|
|
640
|
+
eligibilityMode PromoCodeEligibilityMode @default(SELECTED_TIERS)
|
|
641
|
+
/// Null on legacy rows: derived from the discount fields (see promoCodeScope.ts).
|
|
642
|
+
discountType PromoCodeDiscountType?
|
|
643
|
+
/// Percentage codes reduce BashPoints-priced tickets only when this is true.
|
|
644
|
+
discountAppliesToBashPoints Boolean @default(false)
|
|
645
|
+
/// Archived codes stay for history and stop working.
|
|
646
|
+
disabledAt DateTime?
|
|
647
|
+
/// Set when a legacy duplicate or shared pending promoter needs host review.
|
|
648
|
+
legacyReviewFlag String?
|
|
637
649
|
stripeCouponId String?
|
|
638
650
|
discountAmountInCents Int?
|
|
639
651
|
discountAmountPercentage Int?
|
|
@@ -642,16 +654,81 @@ model BashEventPromoCode {
|
|
|
642
654
|
promoterId String?
|
|
643
655
|
meta String?
|
|
644
656
|
bashPointsRewardPerTicket Int? // Host-defined BashPoints per ticket for promoter rewards
|
|
657
|
+
/// Successful orders allowed per account (Bash user id, else normalized email). Null means unlimited.
|
|
658
|
+
maxUsesPerAccount Int?
|
|
645
659
|
promoter Promoter? @relation(fields: [promoterId], references: [id])
|
|
646
|
-
ticketTier TicketTier @relation(fields: [ticketTierId], references: [id])
|
|
660
|
+
ticketTier TicketTier? @relation(fields: [ticketTierId], references: [id])
|
|
661
|
+
bashEvent BashEvent? @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
647
662
|
usedBy User[] @relation("BashEventPromoCodeToUser")
|
|
663
|
+
redemptions PromoCodeRedemption[]
|
|
664
|
+
eligibleTiers BashEventPromoCodeEligibleTier[]
|
|
648
665
|
|
|
649
666
|
@@unique([ticketTierId, code])
|
|
667
|
+
@@index([bashEventId])
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
enum PromoCodeEligibilityMode {
|
|
671
|
+
ALL_TIERS
|
|
672
|
+
SELECTED_TIERS
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
enum PromoCodeDiscountType {
|
|
676
|
+
NONE
|
|
677
|
+
PERCENT
|
|
678
|
+
FIXED_CASH
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/// Tiers a SELECTED_TIERS code applies to. ALL_TIERS codes store none.
|
|
682
|
+
model BashEventPromoCodeEligibleTier {
|
|
683
|
+
promoCodeId String
|
|
684
|
+
ticketTierId String
|
|
685
|
+
promoCode BashEventPromoCode @relation(fields: [promoCodeId], references: [id], onDelete: Cascade)
|
|
686
|
+
ticketTier TicketTier @relation(fields: [ticketTierId], references: [id], onDelete: Cascade)
|
|
687
|
+
|
|
688
|
+
@@id([promoCodeId, ticketTierId])
|
|
689
|
+
@@index([ticketTierId])
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
enum PromoCodeRedemptionStatus {
|
|
693
|
+
Reserved
|
|
694
|
+
Consumed
|
|
695
|
+
Released
|
|
696
|
+
Refunded
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/// One row per order that used a promo code. `maxRedemptions` counts Consumed plus unexpired Reserved rows.
|
|
700
|
+
model PromoCodeRedemption {
|
|
701
|
+
id String @id @default(cuid())
|
|
702
|
+
promoCodeId String
|
|
703
|
+
userId String?
|
|
704
|
+
normalizedEmail String?
|
|
705
|
+
checkoutId String?
|
|
706
|
+
stripeCheckoutSessionId String? @unique
|
|
707
|
+
stripePaymentIntentId String? @unique
|
|
708
|
+
bashPointsPurchaseRef String? @unique
|
|
709
|
+
/// First ticket of a pay-at-door reservation that stored this code.
|
|
710
|
+
payAtDoorTicketId String? @unique
|
|
711
|
+
status PromoCodeRedemptionStatus @default(Reserved)
|
|
712
|
+
expiresAt DateTime?
|
|
713
|
+
consumedAt DateTime?
|
|
714
|
+
releasedAt DateTime?
|
|
715
|
+
refundedAt DateTime?
|
|
716
|
+
createdAt DateTime @default(now())
|
|
717
|
+
updatedAt DateTime @updatedAt
|
|
718
|
+
|
|
719
|
+
promoCode BashEventPromoCode @relation(fields: [promoCodeId], references: [id], onDelete: Restrict)
|
|
720
|
+
|
|
721
|
+
@@index([promoCodeId, status])
|
|
722
|
+
@@index([promoCodeId, userId])
|
|
723
|
+
@@index([promoCodeId, normalizedEmail])
|
|
724
|
+
@@index([status, expiresAt])
|
|
650
725
|
}
|
|
651
726
|
|
|
652
727
|
model Promoter {
|
|
653
728
|
id String @id @default(cuid())
|
|
654
|
-
|
|
729
|
+
/// The promoter's user id once known. Null for a pending invite (see invitedEmail).
|
|
730
|
+
/// Partial unique index (promotedForBash, invitedEmail) WHERE userId IS NULL lives in SQL.
|
|
731
|
+
promoterId String?
|
|
655
732
|
promotedForBash String
|
|
656
733
|
level Int @default(1)
|
|
657
734
|
isActive Boolean @default(true)
|
|
@@ -1016,7 +1093,9 @@ model BashEvent {
|
|
|
1016
1093
|
/// When true, the "Group up" section is hidden on the bash detail page.
|
|
1017
1094
|
hideGroupUp Boolean @default(false)
|
|
1018
1095
|
/// When true, the "Services open to" box is hidden on the bash detail page.
|
|
1019
|
-
hideServicesOpenTo Boolean @default(
|
|
1096
|
+
hideServicesOpenTo Boolean @default(true)
|
|
1097
|
+
/// When true, the live location box is hidden on the bash detail page.
|
|
1098
|
+
hideLiveLocation Boolean @default(true)
|
|
1020
1099
|
/// When true (default), cancelling the bash auto-refunds paid ticket holders. Hosts may set false only before any ticket/RSVP exists.
|
|
1021
1100
|
refundsGuaranteedOnCancellation Boolean @default(true)
|
|
1022
1101
|
/// When true, host may postpone after tickets exist. May only flip false→true before any ticket/RSVP exists.
|
|
@@ -1072,6 +1151,9 @@ model BashEvent {
|
|
|
1072
1151
|
artistPayoutRate Float?
|
|
1073
1152
|
topPromoterPrize String? // Optional prize label: "Free table for your crew"
|
|
1074
1153
|
promoterLeaderboardIsPublic Boolean @default(false) // Host opts in to public leaderboard
|
|
1154
|
+
/// Host opt-in for promoter requests, the public leaderboard, and the prize.
|
|
1155
|
+
/// Off hides those settings and public surfaces. Codes, attribution, and commission agreements stay.
|
|
1156
|
+
promoterToolsEnabled Boolean @default(false)
|
|
1075
1157
|
/// When true, the bash detail promo-code request CTA is hidden from guests (in-app notifications still work for hosts).
|
|
1076
1158
|
hideGuestPromoCodeRequest Boolean @default(true)
|
|
1077
1159
|
showAttendees Boolean @default(true)
|
|
@@ -1216,6 +1298,10 @@ model BashEvent {
|
|
|
1216
1298
|
albumModerationEnabled Boolean @default(false)
|
|
1217
1299
|
/// Opt-in post-event attendee networking
|
|
1218
1300
|
postEventNetworkingEnabled Boolean @default(false)
|
|
1301
|
+
/// Intros at this bash. Off until the host turns it on.
|
|
1302
|
+
introsMode IntrosEventMode @default(Off)
|
|
1303
|
+
introsParticipations IntrosEventParticipation[]
|
|
1304
|
+
introductions Introduction[]
|
|
1219
1305
|
|
|
1220
1306
|
// Host broadcast fields
|
|
1221
1307
|
postEventMessageSent Boolean @default(false)
|
|
@@ -1313,6 +1399,7 @@ model BashEvent {
|
|
|
1313
1399
|
hostPromoterPayouts HostPromoterPayout[]
|
|
1314
1400
|
ticketGiftGrants TicketGiftGrant[]
|
|
1315
1401
|
ticketTiers TicketTier[]
|
|
1402
|
+
promoCodes BashEventPromoCode[]
|
|
1316
1403
|
tierReleaseReminders TierReleaseReminder[]
|
|
1317
1404
|
favoritedBy UserFavorite[]
|
|
1318
1405
|
userPromoCodeRedemption UserPromoCodeRedemption[]
|
|
@@ -3626,6 +3713,7 @@ model TicketTier {
|
|
|
3626
3713
|
isDonationTier Boolean?
|
|
3627
3714
|
hidden Boolean?
|
|
3628
3715
|
promoCodes BashEventPromoCode[]
|
|
3716
|
+
promoCodeEligibility BashEventPromoCodeEligibleTier[]
|
|
3629
3717
|
tickets Ticket[]
|
|
3630
3718
|
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
3631
3719
|
waitList User[] @relation("TicketTierToUser")
|
|
@@ -4640,11 +4728,15 @@ model User {
|
|
|
4640
4728
|
/// App Store originalTransactionId when membership is billed via StoreKit IAP.
|
|
4641
4729
|
membershipAppleOriginalTransactionId String? @unique
|
|
4642
4730
|
/// Which provider owns the active membership billing relationship.
|
|
4643
|
-
membershipBillingProvider String? // "stripe" | "apple" | null
|
|
4731
|
+
membershipBillingProvider String? // "stripe" | "apple" | "google" | null
|
|
4732
|
+
/// Current Google Play purchase token when membership is billed via Play Billing.
|
|
4733
|
+
membershipGooglePurchaseToken String? @unique
|
|
4644
4734
|
/// Optional consumer BashPass subscription (waives guest platform fee on tickets; monthly BashPoints).
|
|
4645
4735
|
bashPassStripeSubscriptionId String? @unique
|
|
4646
4736
|
/// App Store originalTransactionId when BashPass is billed via StoreKit IAP.
|
|
4647
4737
|
bashPassAppleOriginalTransactionId String? @unique
|
|
4738
|
+
/// Current Google Play purchase token when BashPass is billed via Play Billing.
|
|
4739
|
+
bashPassGooglePurchaseToken String? @unique
|
|
4648
4740
|
bashPassCurrentPeriodEnd DateTime?
|
|
4649
4741
|
/// Stripe price tier for standalone BashPass; effective tier may also come from membership bundle.
|
|
4650
4742
|
bashPassTier BashPassTier?
|
|
@@ -4704,6 +4796,7 @@ model User {
|
|
|
4704
4796
|
birthdayOfferOptIns UserBirthdayOfferOptIn[]
|
|
4705
4797
|
birthdayOfferDeliveries BirthdayOfferDelivery[]
|
|
4706
4798
|
birthdayBoostGrants BirthdayBoostGrant[]
|
|
4799
|
+
playPurchases PlayPurchase[]
|
|
4707
4800
|
birthdayRewardRedemptions BirthdayRewardRedemption[]
|
|
4708
4801
|
birthdayRewardFavorites BirthdayRewardFavorite[]
|
|
4709
4802
|
birthdayDealSuggestions BirthdayDealSuggestion[]
|
|
@@ -4849,6 +4942,11 @@ model User {
|
|
|
4849
4942
|
connectionRequestsReceived UserConnection[] @relation("ConnectionRequestsReceived")
|
|
4850
4943
|
interestExpressedByMe InterestExpression[] @relation("InterestExpressedByMe")
|
|
4851
4944
|
interestExpressedToMe InterestExpression[] @relation("InterestExpressedToMe")
|
|
4945
|
+
introsProfile IntrosProfile?
|
|
4946
|
+
introsAttributes IntrosProfileAttribute[]
|
|
4947
|
+
introsEventParticipations IntrosEventParticipation[]
|
|
4948
|
+
warmSuggestionsMade WarmIntroSuggestion[] @relation("WarmSuggestionFacilitator")
|
|
4949
|
+
facilitatedIntroductions Introduction[] @relation("IntroFacilitator")
|
|
4852
4950
|
links UserLink[]
|
|
4853
4951
|
preferences UserPreferences?
|
|
4854
4952
|
rankings UserRankings?
|
|
@@ -5093,6 +5191,8 @@ model UserPreferences {
|
|
|
5093
5191
|
personalityType String?
|
|
5094
5192
|
/// Self-reported locus of control: internal | external | mixed
|
|
5095
5193
|
locusOfControl String?
|
|
5194
|
+
/// Warm Intro invitations from connections. Null means the person has not chosen.
|
|
5195
|
+
warmIntroInvites WarmIntroInvitePref?
|
|
5096
5196
|
blockSearchEngineIndex Boolean @default(false)
|
|
5097
5197
|
autoAddEventAttendees Boolean @default(true)
|
|
5098
5198
|
trackFirstEventAttended Boolean @default(true)
|
|
@@ -5429,6 +5529,262 @@ model InterestExpression {
|
|
|
5429
5529
|
@@index([targetId])
|
|
5430
5530
|
}
|
|
5431
5531
|
|
|
5532
|
+
enum IntrosStatus {
|
|
5533
|
+
Off
|
|
5534
|
+
Active
|
|
5535
|
+
Paused
|
|
5536
|
+
}
|
|
5537
|
+
|
|
5538
|
+
enum IntrosIntent {
|
|
5539
|
+
Friends
|
|
5540
|
+
Professional
|
|
5541
|
+
MentorSeek
|
|
5542
|
+
MentorOffer
|
|
5543
|
+
Collaborator
|
|
5544
|
+
Romance
|
|
5545
|
+
}
|
|
5546
|
+
|
|
5547
|
+
enum IntrosWarmAudience {
|
|
5548
|
+
None
|
|
5549
|
+
Connections
|
|
5550
|
+
ConnectionsAndHosts
|
|
5551
|
+
}
|
|
5552
|
+
|
|
5553
|
+
enum WarmIntroInvitePref {
|
|
5554
|
+
Off
|
|
5555
|
+
Anonymous
|
|
5556
|
+
Named
|
|
5557
|
+
}
|
|
5558
|
+
|
|
5559
|
+
enum IntrosEventMode {
|
|
5560
|
+
Off
|
|
5561
|
+
Platonic
|
|
5562
|
+
All
|
|
5563
|
+
}
|
|
5564
|
+
|
|
5565
|
+
enum IntrosAttributeKind {
|
|
5566
|
+
BigFive
|
|
5567
|
+
MyersBriggs
|
|
5568
|
+
LocusOfControl
|
|
5569
|
+
CliftonStrengths
|
|
5570
|
+
EmotionalIntelligence
|
|
5571
|
+
HumanDesign
|
|
5572
|
+
}
|
|
5573
|
+
|
|
5574
|
+
enum IntrosVisibility {
|
|
5575
|
+
OnlyMe
|
|
5576
|
+
RevealedIntros
|
|
5577
|
+
}
|
|
5578
|
+
|
|
5579
|
+
enum IntroductionSource {
|
|
5580
|
+
BashSuggested
|
|
5581
|
+
Warm
|
|
5582
|
+
}
|
|
5583
|
+
|
|
5584
|
+
enum IntroductionMode {
|
|
5585
|
+
Mystery
|
|
5586
|
+
Known
|
|
5587
|
+
}
|
|
5588
|
+
|
|
5589
|
+
enum IntroductionState {
|
|
5590
|
+
Open
|
|
5591
|
+
Mutual
|
|
5592
|
+
Revealed
|
|
5593
|
+
Closed
|
|
5594
|
+
}
|
|
5595
|
+
|
|
5596
|
+
enum IntroductionClosedReason {
|
|
5597
|
+
Declined
|
|
5598
|
+
Withdrawn
|
|
5599
|
+
Expired
|
|
5600
|
+
NotRegistered
|
|
5601
|
+
Blocked
|
|
5602
|
+
EventCancelled
|
|
5603
|
+
IntrosDisabled
|
|
5604
|
+
ConsentRevoked
|
|
5605
|
+
}
|
|
5606
|
+
|
|
5607
|
+
enum IntroInterest {
|
|
5608
|
+
Pending
|
|
5609
|
+
Interested
|
|
5610
|
+
Declined
|
|
5611
|
+
Postponed
|
|
5612
|
+
Withdrawn
|
|
5613
|
+
}
|
|
5614
|
+
|
|
5615
|
+
enum RevealSource {
|
|
5616
|
+
EventStart
|
|
5617
|
+
EarlyReveal
|
|
5618
|
+
Warm
|
|
5619
|
+
}
|
|
5620
|
+
|
|
5621
|
+
enum EarlyRevealStatus {
|
|
5622
|
+
Requested
|
|
5623
|
+
Approved
|
|
5624
|
+
Completed
|
|
5625
|
+
Declined
|
|
5626
|
+
Expired
|
|
5627
|
+
Cancelled
|
|
5628
|
+
Refunded
|
|
5629
|
+
}
|
|
5630
|
+
|
|
5631
|
+
enum EarlyRevealPaymentMethod {
|
|
5632
|
+
Stripe
|
|
5633
|
+
AppleIap
|
|
5634
|
+
BashPoints
|
|
5635
|
+
}
|
|
5636
|
+
|
|
5637
|
+
model IntrosProfile {
|
|
5638
|
+
id String @id @default(cuid())
|
|
5639
|
+
userId String @unique
|
|
5640
|
+
status IntrosStatus @default(Off)
|
|
5641
|
+
pausedUntil DateTime?
|
|
5642
|
+
consentVersion Int @default(1)
|
|
5643
|
+
activatedAt DateTime?
|
|
5644
|
+
globalMatchingAt DateTime?
|
|
5645
|
+
romanceAt DateTime?
|
|
5646
|
+
psychologyExperimentAt DateTime?
|
|
5647
|
+
warmSuggestionAudience IntrosWarmAudience @default(None)
|
|
5648
|
+
intents IntrosIntent[]
|
|
5649
|
+
shortIntro String? @db.VarChar(140)
|
|
5650
|
+
conversationTopics String[] @default([])
|
|
5651
|
+
professionalInterests String[] @default([])
|
|
5652
|
+
travelRadiusMiles Int?
|
|
5653
|
+
romanceSeekingGenders String[] @default([])
|
|
5654
|
+
romanceAgeMin Int?
|
|
5655
|
+
romanceAgeMax Int?
|
|
5656
|
+
shareRegistrationStatus Boolean @default(false)
|
|
5657
|
+
revealOnlyAfterCheckIn Boolean @default(false)
|
|
5658
|
+
notifyIntros Boolean @default(true)
|
|
5659
|
+
legacyImportedAt DateTime?
|
|
5660
|
+
createdAt DateTime @default(now())
|
|
5661
|
+
updatedAt DateTime @updatedAt
|
|
5662
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
5663
|
+
}
|
|
5664
|
+
|
|
5665
|
+
model IntrosProfileAttribute {
|
|
5666
|
+
id String @id @default(cuid())
|
|
5667
|
+
userId String
|
|
5668
|
+
kind IntrosAttributeKind
|
|
5669
|
+
value Json
|
|
5670
|
+
source String
|
|
5671
|
+
visibility IntrosVisibility @default(OnlyMe)
|
|
5672
|
+
allowExperimentalMatching Boolean @default(false)
|
|
5673
|
+
updatedAt DateTime @updatedAt
|
|
5674
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
5675
|
+
|
|
5676
|
+
@@unique([userId, kind])
|
|
5677
|
+
}
|
|
5678
|
+
|
|
5679
|
+
model IntrosEventParticipation {
|
|
5680
|
+
id String @id @default(cuid())
|
|
5681
|
+
userId String
|
|
5682
|
+
bashEventId String
|
|
5683
|
+
optedInAt DateTime @default(now())
|
|
5684
|
+
optedOutAt DateTime?
|
|
5685
|
+
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
5686
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
5687
|
+
|
|
5688
|
+
@@unique([userId, bashEventId])
|
|
5689
|
+
@@index([bashEventId])
|
|
5690
|
+
}
|
|
5691
|
+
|
|
5692
|
+
model IntrosPair {
|
|
5693
|
+
id String @id @default(cuid())
|
|
5694
|
+
userLowId String
|
|
5695
|
+
userHighId String
|
|
5696
|
+
lastSuggestedAt DateTime?
|
|
5697
|
+
revealCount Int @default(0)
|
|
5698
|
+
lastRevealedAt DateTime?
|
|
5699
|
+
cooldownUntil DateTime?
|
|
5700
|
+
hiddenByLowAt DateTime?
|
|
5701
|
+
hiddenByHighAt DateTime?
|
|
5702
|
+
introductions Introduction[]
|
|
5703
|
+
|
|
5704
|
+
@@unique([userLowId, userHighId])
|
|
5705
|
+
}
|
|
5706
|
+
|
|
5707
|
+
model Introduction {
|
|
5708
|
+
id String @id @default(cuid())
|
|
5709
|
+
pairId String
|
|
5710
|
+
bashEventId String?
|
|
5711
|
+
source IntroductionSource
|
|
5712
|
+
mode IntroductionMode
|
|
5713
|
+
matchedIntent IntrosIntent?
|
|
5714
|
+
state IntroductionState @default(Open)
|
|
5715
|
+
closedReason IntroductionClosedReason?
|
|
5716
|
+
interestLow IntroInterest @default(Pending)
|
|
5717
|
+
interestHigh IntroInterest @default(Pending)
|
|
5718
|
+
interestLowAt DateTime?
|
|
5719
|
+
interestHighAt DateTime?
|
|
5720
|
+
mutedLow Boolean @default(false)
|
|
5721
|
+
mutedHigh Boolean @default(false)
|
|
5722
|
+
saidHiLowAt DateTime?
|
|
5723
|
+
saidHiHighAt DateTime?
|
|
5724
|
+
facilitationOkLowAt DateTime?
|
|
5725
|
+
facilitationOkHighAt DateTime?
|
|
5726
|
+
facilitatorId String?
|
|
5727
|
+
facilitatorNote String? @db.VarChar(280)
|
|
5728
|
+
facilitatorMadeAt DateTime?
|
|
5729
|
+
revealAt DateTime?
|
|
5730
|
+
revealedAt DateTime?
|
|
5731
|
+
revealSource RevealSource?
|
|
5732
|
+
nudgedAt DateTime?
|
|
5733
|
+
explanationCodes String[] @default([])
|
|
5734
|
+
scoreComponents Json?
|
|
5735
|
+
ruleVersion Int @default(1)
|
|
5736
|
+
expiresAt DateTime?
|
|
5737
|
+
version Int @default(0)
|
|
5738
|
+
createdAt DateTime @default(now())
|
|
5739
|
+
pair IntrosPair @relation(fields: [pairId], references: [id], onDelete: Cascade)
|
|
5740
|
+
bashEvent BashEvent? @relation(fields: [bashEventId], references: [id], onDelete: SetNull)
|
|
5741
|
+
facilitator User? @relation("IntroFacilitator", fields: [facilitatorId], references: [id], onDelete: SetNull)
|
|
5742
|
+
earlyReveals EarlyRevealRequest[]
|
|
5743
|
+
|
|
5744
|
+
@@index([bashEventId, state])
|
|
5745
|
+
@@index([facilitatorId])
|
|
5746
|
+
@@index([state, revealAt])
|
|
5747
|
+
}
|
|
5748
|
+
|
|
5749
|
+
model WarmIntroSuggestion {
|
|
5750
|
+
id String @id @default(cuid())
|
|
5751
|
+
facilitatorId String
|
|
5752
|
+
pairId String
|
|
5753
|
+
bashEventId String?
|
|
5754
|
+
linkedIntroductionId String?
|
|
5755
|
+
reasonCodes String[] @default([])
|
|
5756
|
+
madeAt DateTime?
|
|
5757
|
+
dismissedAt DateTime?
|
|
5758
|
+
offeredIntroductionId String?
|
|
5759
|
+
createdAt DateTime @default(now())
|
|
5760
|
+
facilitator User @relation("WarmSuggestionFacilitator", fields: [facilitatorId], references: [id], onDelete: Cascade)
|
|
5761
|
+
|
|
5762
|
+
@@unique([facilitatorId, pairId, bashEventId])
|
|
5763
|
+
@@index([facilitatorId, createdAt])
|
|
5764
|
+
}
|
|
5765
|
+
|
|
5766
|
+
model EarlyRevealRequest {
|
|
5767
|
+
id String @id @default(cuid())
|
|
5768
|
+
introductionId String
|
|
5769
|
+
requesterId String
|
|
5770
|
+
status EarlyRevealStatus @default(Requested)
|
|
5771
|
+
priceCents Int
|
|
5772
|
+
currency String @default("usd")
|
|
5773
|
+
paymentMethod EarlyRevealPaymentMethod?
|
|
5774
|
+
stripePaymentIntentId String? @unique
|
|
5775
|
+
appleTransactionId String? @unique
|
|
5776
|
+
bashCreditTransactionId String?
|
|
5777
|
+
idempotencyKey String @unique
|
|
5778
|
+
approvedAt DateTime?
|
|
5779
|
+
expiresAt DateTime
|
|
5780
|
+
createdAt DateTime @default(now())
|
|
5781
|
+
updatedAt DateTime @updatedAt
|
|
5782
|
+
introduction Introduction @relation(fields: [introductionId], references: [id], onDelete: Cascade)
|
|
5783
|
+
|
|
5784
|
+
@@index([introductionId])
|
|
5785
|
+
@@index([status, updatedAt])
|
|
5786
|
+
}
|
|
5787
|
+
|
|
5432
5788
|
model BiometricCredential {
|
|
5433
5789
|
id String @id @default(cuid())
|
|
5434
5790
|
userId String
|
|
@@ -5593,6 +5949,33 @@ model ServiceSubscriptionCounts {
|
|
|
5593
5949
|
subscriptionCount UserSubscription? @relation("subscriptionCount")
|
|
5594
5950
|
}
|
|
5595
5951
|
|
|
5952
|
+
/// One row per Google Play purchase token. Renewals update the same row.
|
|
5953
|
+
/// A subscription replacement inserts a new row and keeps the previous token.
|
|
5954
|
+
model PlayPurchase {
|
|
5955
|
+
id String @id @default(cuid())
|
|
5956
|
+
purchaseToken String @unique
|
|
5957
|
+
linkedPurchaseToken String?
|
|
5958
|
+
productId String
|
|
5959
|
+
userId String
|
|
5960
|
+
family String
|
|
5961
|
+
purchaseState String
|
|
5962
|
+
expiryTime DateTime?
|
|
5963
|
+
orderId String?
|
|
5964
|
+
grantedAt DateTime?
|
|
5965
|
+
acknowledgedAt DateTime?
|
|
5966
|
+
consumedAt DateTime?
|
|
5967
|
+
finishError String?
|
|
5968
|
+
boostTargetType String?
|
|
5969
|
+
boostTargetId String?
|
|
5970
|
+
featuredUntil DateTime?
|
|
5971
|
+
createdAt DateTime @default(now())
|
|
5972
|
+
updatedAt DateTime @updatedAt
|
|
5973
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
5974
|
+
|
|
5975
|
+
@@index([userId])
|
|
5976
|
+
@@index([linkedPurchaseToken])
|
|
5977
|
+
}
|
|
5978
|
+
|
|
5596
5979
|
model UserSubscription {
|
|
5597
5980
|
id String @id @default(cuid())
|
|
5598
5981
|
ownerId String @unique
|
|
@@ -5601,6 +5984,8 @@ model UserSubscription {
|
|
|
5601
5984
|
stripeCheckoutSessionId String? @unique
|
|
5602
5985
|
/// App Store originalTransactionId when listing seats are billed via StoreKit IAP.
|
|
5603
5986
|
appleOriginalTransactionId String? @unique
|
|
5987
|
+
/// Current Google Play purchase token when listing seats are billed via Play Billing.
|
|
5988
|
+
googlePurchaseToken String? @unique
|
|
5604
5989
|
type MembershipTier?
|
|
5605
5990
|
status UserSubscriptionStatus?
|
|
5606
5991
|
subscriptionCountId String @unique
|
|
@@ -5614,6 +5999,7 @@ model UserSubscription {
|
|
|
5614
5999
|
@@index([stripeCheckoutSessionId])
|
|
5615
6000
|
@@index([stripeSubscriptionId])
|
|
5616
6001
|
@@index([appleOriginalTransactionId])
|
|
6002
|
+
@@index([googlePurchaseToken])
|
|
5617
6003
|
}
|
|
5618
6004
|
|
|
5619
6005
|
model Service {
|
|
@@ -6084,7 +6470,7 @@ model VendorSpaceRequirements {
|
|
|
6084
6470
|
vendorId String @unique
|
|
6085
6471
|
boothSize String @default("10x10")
|
|
6086
6472
|
customSize String?
|
|
6087
|
-
hasTent Boolean @default(
|
|
6473
|
+
hasTent Boolean @default(true)
|
|
6088
6474
|
tableCount String @default("1")
|
|
6089
6475
|
hasChairs Boolean @default(false)
|
|
6090
6476
|
needsElectricity Boolean @default(false)
|
|
@@ -8513,6 +8899,8 @@ model UserReport {
|
|
|
8513
8899
|
reporterId String
|
|
8514
8900
|
reportedId String
|
|
8515
8901
|
bashEventId String?
|
|
8902
|
+
/// Optional Intros introduction this report is about. The reporter may not know the other person yet.
|
|
8903
|
+
introductionId String?
|
|
8516
8904
|
reason String
|
|
8517
8905
|
details String
|
|
8518
8906
|
createdAt DateTime @default(now())
|
|
@@ -8965,6 +9353,12 @@ enum NotificationType {
|
|
|
8965
9353
|
InterestExpressedAnonymous
|
|
8966
9354
|
/// Intros: both people sent a signal — unlocks chat
|
|
8967
9355
|
IntroMutual
|
|
9356
|
+
/// Intros V2: never identifies anyone before a reveal
|
|
9357
|
+
IntrosUpdate
|
|
9358
|
+
/// Intros V2: identities, sent only to the two people
|
|
9359
|
+
IntrosRevealed
|
|
9360
|
+
/// Intros V2: warm invitations and facilitator suggestions
|
|
9361
|
+
IntrosWarm
|
|
8968
9362
|
}
|
|
8969
9363
|
|
|
8970
9364
|
/// Opt-in reminder for a scheduled tier release (v1.5).
|
|
@@ -11614,6 +12008,7 @@ enum CreditSourceType {
|
|
|
11614
12008
|
CompetitionFinalist // Adventures reward for reaching a finalist placement
|
|
11615
12009
|
CompetitionWin // Adventures reward for winning a competition prize
|
|
11616
12010
|
HornClear // Stuff the horn: 5 points per clear, 100 per UTC day
|
|
12011
|
+
IntrosEarlyReveal // BashPoints spent on a paid early identity reveal
|
|
11617
12012
|
}
|
|
11618
12013
|
|
|
11619
12014
|
enum ReferralTier {
|
|
@@ -12472,6 +12867,13 @@ enum AuditAction {
|
|
|
12472
12867
|
ORG_TAX_DOCUMENT_REVIEWED
|
|
12473
12868
|
ORG_INSURANCE_CERTIFICATE_SUBMITTED
|
|
12474
12869
|
ORG_INSURANCE_CERTIFICATE_REVIEWED
|
|
12870
|
+
INTROS_REVEALED
|
|
12871
|
+
INTROS_REVEAL_BLOCKED
|
|
12872
|
+
INTROS_WARM_ACCEPTED
|
|
12873
|
+
INTROS_EARLY_REVEAL_APPROVED
|
|
12874
|
+
INTROS_EARLY_REVEAL_PAID
|
|
12875
|
+
INTROS_REFUND_ISSUED
|
|
12876
|
+
INTROS_PAYMENT_RECONCILED
|
|
12475
12877
|
}
|
|
12476
12878
|
|
|
12477
12879
|
enum AuditCategory {
|
|
@@ -12487,6 +12889,7 @@ enum AuditCategory {
|
|
|
12487
12889
|
Compliance
|
|
12488
12890
|
Security
|
|
12489
12891
|
Organization
|
|
12892
|
+
Intros
|
|
12490
12893
|
}
|
|
12491
12894
|
|
|
12492
12895
|
enum AuditSeverity {
|
|
@@ -13070,18 +13473,36 @@ model AppliedDiscount {
|
|
|
13070
13473
|
displayReason String? // "Early Bird Discount" for receipt
|
|
13071
13474
|
internalNote String? // For support/debugging
|
|
13072
13475
|
|
|
13476
|
+
/// BashPoints taken off by a percentage code that applies to BashPoints tiers.
|
|
13477
|
+
pointsDiscounted Int?
|
|
13478
|
+
/// Tickets this row attributes to the promoter (free and BashPoints included).
|
|
13479
|
+
attributedTicketCount Int?
|
|
13480
|
+
|
|
13481
|
+
/// Provisional until payment succeeds; readers count Final rows with no refundedAt.
|
|
13482
|
+
status AppliedDiscountStatus @default(Final)
|
|
13483
|
+
finalizedAt DateTime?
|
|
13484
|
+
refundedAt DateTime?
|
|
13485
|
+
|
|
13073
13486
|
// Relations
|
|
13074
13487
|
checkout Checkout? @relation(fields: [checkoutId], references: [id])
|
|
13075
13488
|
ticket Ticket? @relation(fields: [ticketId], references: [id])
|
|
13076
13489
|
ticketTier TicketTier? @relation(fields: [ticketTierId], references: [id])
|
|
13077
13490
|
attributionUser User? @relation("DiscountAttribution", fields: [attributionUserId], references: [id])
|
|
13078
13491
|
|
|
13492
|
+
@@unique([checkoutId, sourceId, ticketId])
|
|
13079
13493
|
@@index([checkoutId])
|
|
13494
|
+
@@index([checkoutId, status])
|
|
13080
13495
|
@@index([sourceType, sourceId])
|
|
13081
13496
|
@@index([attributionUserId])
|
|
13082
13497
|
@@index([createdAt])
|
|
13083
13498
|
}
|
|
13084
13499
|
|
|
13500
|
+
enum AppliedDiscountStatus {
|
|
13501
|
+
Provisional
|
|
13502
|
+
Final
|
|
13503
|
+
Voided
|
|
13504
|
+
}
|
|
13505
|
+
|
|
13085
13506
|
// Special offers - automatic, visible, conversion-oriented deals
|
|
13086
13507
|
model SpecialOffer {
|
|
13087
13508
|
id String @id @default(cuid())
|
|
@@ -41,6 +41,9 @@ describe("appleIapProducts", () => {
|
|
|
41
41
|
expect(
|
|
42
42
|
getAppleIapProduct("community.bash.us.boost.7d")?.family
|
|
43
43
|
).toBe("feature_boost");
|
|
44
|
+
expect(getAppleIapProduct("community.bash.us.intros.earlyreveal")?.family).toBe(
|
|
45
|
+
"early_reveal"
|
|
46
|
+
);
|
|
44
47
|
});
|
|
45
48
|
|
|
46
49
|
it("listAppleIapProductIds filters by family", () => {
|
|
@@ -54,6 +54,10 @@ describe("bashSectionTitleForBashType", () => {
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
it("scope rows use destination copy", () => {
|
|
57
|
+
expect(bashSectionTitleForBashType("Local")).toBe(
|
|
58
|
+
"City & Community Events"
|
|
59
|
+
);
|
|
60
|
+
expect(bashSectionTitleForBashType("State")).toBe("State Events");
|
|
57
61
|
expect(bashSectionTitleForBashType("National")).toBe(
|
|
58
62
|
"Across the country"
|
|
59
63
|
);
|
|
@@ -15,10 +15,31 @@ describe("discoveryScope", () => {
|
|
|
15
15
|
);
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
it("infers State from state
|
|
18
|
+
it("infers State from a state-run event, not from travel or sponsorship", () => {
|
|
19
19
|
expect(inferDiscoveryScopeFromText("Utah State Fair")).toBe(
|
|
20
20
|
DiscoveryScope.State
|
|
21
21
|
);
|
|
22
|
+
expect(inferDiscoveryScopeFromText("People are coming from statewide")).toBe(
|
|
23
|
+
DiscoveryScope.Unspecified
|
|
24
|
+
);
|
|
25
|
+
expect(
|
|
26
|
+
inferDiscoveryScopeFromText("Sponsored by the Utah state agency office")
|
|
27
|
+
).toBe(DiscoveryScope.Unspecified);
|
|
28
|
+
expect(
|
|
29
|
+
inferDiscoveryScopeFromText("Organized by Utah State Parks")
|
|
30
|
+
).toBe(DiscoveryScope.State);
|
|
31
|
+
expect(
|
|
32
|
+
inferDiscoveryScopeFromText("Neighborhood party sponsored by the state")
|
|
33
|
+
).toBe(DiscoveryScope.Unspecified);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("infers Local from the organizer, not from how close the party is", () => {
|
|
37
|
+
expect(
|
|
38
|
+
inferDiscoveryScopeFromText("City of Provo parks and recreation concert")
|
|
39
|
+
).toBe(DiscoveryScope.Local);
|
|
40
|
+
expect(inferDiscoveryScopeFromText("Sugar House block party")).toBe(
|
|
41
|
+
DiscoveryScope.Unspecified
|
|
42
|
+
);
|
|
22
43
|
});
|
|
23
44
|
|
|
24
45
|
it("infers National from destination brands", () => {
|