@bash-app/bash-common 30.246.0 → 30.253.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/README.md +4 -0
- package/dist/__tests__/bashSectionTitleForBashType.test.js +32 -1
- package/dist/__tests__/bashSectionTitleForBashType.test.js.map +1 -1
- package/dist/__tests__/definitionsHelpers.test.d.ts +2 -0
- package/dist/__tests__/definitionsHelpers.test.d.ts.map +1 -0
- package/dist/__tests__/definitionsHelpers.test.js +85 -0
- package/dist/__tests__/definitionsHelpers.test.js.map +1 -0
- package/dist/__tests__/extendedSchemas.test.d.ts +2 -0
- package/dist/__tests__/extendedSchemas.test.d.ts.map +1 -0
- package/dist/__tests__/extendedSchemas.test.js +40 -0
- package/dist/__tests__/extendedSchemas.test.js.map +1 -0
- package/dist/__tests__/membershipDefinitions.test.d.ts +2 -0
- package/dist/__tests__/membershipDefinitions.test.d.ts.map +1 -0
- package/dist/__tests__/membershipDefinitions.test.js +95 -0
- package/dist/__tests__/membershipDefinitions.test.js.map +1 -0
- package/dist/__tests__/ticketAdmission.test.d.ts +5 -0
- package/dist/__tests__/ticketAdmission.test.d.ts.map +1 -0
- package/dist/__tests__/ticketAdmission.test.js +42 -0
- package/dist/__tests__/ticketAdmission.test.js.map +1 -0
- package/dist/__tests__/utmAttribution.test.d.ts +2 -0
- package/dist/__tests__/utmAttribution.test.d.ts.map +1 -0
- package/dist/__tests__/utmAttribution.test.js +92 -0
- package/dist/__tests__/utmAttribution.test.js.map +1 -0
- package/dist/definitions.d.ts +18 -5
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +84 -22
- package/dist/definitions.js.map +1 -1
- package/dist/extendedSchemas.d.ts +41 -1
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js +27 -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/sms/smsTemplates.d.ts +27 -0
- package/dist/sms/smsTemplates.d.ts.map +1 -0
- package/dist/sms/smsTemplates.js +11 -0
- package/dist/sms/smsTemplates.js.map +1 -0
- package/dist/utils/__tests__/addressUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/addressUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/addressUtils.test.js +138 -0
- package/dist/utils/__tests__/addressUtils.test.js.map +1 -0
- package/dist/utils/__tests__/apiUtils.test.d.ts +5 -0
- package/dist/utils/__tests__/apiUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/apiUtils.test.js +161 -0
- package/dist/utils/__tests__/apiUtils.test.js.map +1 -0
- package/dist/utils/__tests__/arrayUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/arrayUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/arrayUtils.test.js +23 -0
- package/dist/utils/__tests__/arrayUtils.test.js.map +1 -0
- package/dist/utils/__tests__/blogUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/blogUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/blogUtils.test.js +102 -0
- package/dist/utils/__tests__/blogUtils.test.js.map +1 -0
- package/dist/utils/__tests__/dateTimeUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/dateTimeUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/dateTimeUtils.test.js +180 -0
- package/dist/utils/__tests__/dateTimeUtils.test.js.map +1 -0
- package/dist/utils/__tests__/discountEngine/discountCalculator.test.d.ts +2 -0
- package/dist/utils/__tests__/discountEngine/discountCalculator.test.d.ts.map +1 -0
- package/dist/utils/__tests__/discountEngine/discountCalculator.test.js +356 -0
- package/dist/utils/__tests__/discountEngine/discountCalculator.test.js.map +1 -0
- package/dist/utils/__tests__/generalDateTimeUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/generalDateTimeUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/generalDateTimeUtils.test.js +26 -0
- package/dist/utils/__tests__/generalDateTimeUtils.test.js.map +1 -0
- package/dist/utils/__tests__/luxonUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/luxonUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/luxonUtils.test.js +139 -0
- package/dist/utils/__tests__/luxonUtils.test.js.map +1 -0
- package/dist/utils/__tests__/mathUtils.test.d.ts +5 -0
- package/dist/utils/__tests__/mathUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/mathUtils.test.js +26 -0
- package/dist/utils/__tests__/mathUtils.test.js.map +1 -0
- package/dist/utils/__tests__/objUtils.test.d.ts +5 -0
- package/dist/utils/__tests__/objUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/objUtils.test.js +41 -0
- package/dist/utils/__tests__/objUtils.test.js.map +1 -0
- package/dist/utils/__tests__/paymentUtils.test.js +48 -1
- package/dist/utils/__tests__/paymentUtils.test.js.map +1 -1
- package/dist/utils/__tests__/qrCodeUtils.test.js +16 -1
- package/dist/utils/__tests__/qrCodeUtils.test.js.map +1 -1
- package/dist/utils/__tests__/reviewUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/reviewUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/reviewUtils.test.js +49 -0
- package/dist/utils/__tests__/reviewUtils.test.js.map +1 -0
- package/dist/utils/__tests__/slugUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/slugUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/slugUtils.test.js +103 -0
- package/dist/utils/__tests__/slugUtils.test.js.map +1 -0
- package/dist/utils/__tests__/sortUtils.test.d.ts +5 -0
- package/dist/utils/__tests__/sortUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/sortUtils.test.js +28 -0
- package/dist/utils/__tests__/sortUtils.test.js.map +1 -0
- package/dist/utils/__tests__/stringUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/stringUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/stringUtils.test.js +27 -0
- package/dist/utils/__tests__/stringUtils.test.js.map +1 -0
- package/dist/utils/__tests__/ticketListUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/ticketListUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/ticketListUtils.test.js +41 -0
- package/dist/utils/__tests__/ticketListUtils.test.js.map +1 -0
- package/dist/utils/__tests__/typeUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/typeUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/typeUtils.test.js +11 -0
- package/dist/utils/__tests__/typeUtils.test.js.map +1 -0
- package/dist/utils/__tests__/userSubscriptionUtils.test.d.ts +5 -0
- package/dist/utils/__tests__/userSubscriptionUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/userSubscriptionUtils.test.js +66 -0
- package/dist/utils/__tests__/userSubscriptionUtils.test.js.map +1 -0
- package/dist/utils/__tests__/userUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/userUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/userUtils.test.js +34 -0
- package/dist/utils/__tests__/userUtils.test.js.map +1 -0
- package/dist/utils/__tests__/venueTypeFormatter.test.d.ts +2 -0
- package/dist/utils/__tests__/venueTypeFormatter.test.d.ts.map +1 -0
- package/dist/utils/__tests__/venueTypeFormatter.test.js +25 -0
- package/dist/utils/__tests__/venueTypeFormatter.test.js.map +1 -0
- package/dist/utils/service/__tests__/regexUtils.test.d.ts +2 -0
- package/dist/utils/service/__tests__/regexUtils.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/regexUtils.test.js +51 -0
- package/dist/utils/service/__tests__/regexUtils.test.js.map +1 -0
- package/dist/utils/service/__tests__/serviceDBUtils.test.d.ts +2 -0
- package/dist/utils/service/__tests__/serviceDBUtils.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/serviceDBUtils.test.js +17 -0
- package/dist/utils/service/__tests__/serviceDBUtils.test.js.map +1 -0
- package/dist/utils/service/__tests__/serviceFeaturedSortUtils.test.d.ts +2 -0
- package/dist/utils/service/__tests__/serviceFeaturedSortUtils.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/serviceFeaturedSortUtils.test.js +60 -0
- package/dist/utils/service/__tests__/serviceFeaturedSortUtils.test.js.map +1 -0
- package/dist/utils/service/__tests__/serviceUtils.test.d.ts +2 -0
- package/dist/utils/service/__tests__/serviceUtils.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/serviceUtils.test.js +135 -0
- package/dist/utils/service/__tests__/serviceUtils.test.js.map +1 -0
- package/dist/utils/service/serviceFeaturedSortUtils.d.ts.map +1 -1
- package/dist/utils/service/serviceFeaturedSortUtils.js +5 -1
- package/dist/utils/service/serviceFeaturedSortUtils.js.map +1 -1
- package/dist/utils/ticketListUtils.d.ts.map +1 -1
- package/dist/utils/ticketListUtils.js +11 -7
- package/dist/utils/ticketListUtils.js.map +1 -1
- package/package.json +1 -1
- package/prisma/schema.prisma +47 -0
- package/src/__tests__/bashSectionTitleForBashType.test.ts +48 -1
- package/src/__tests__/definitionsHelpers.test.ts +136 -0
- package/src/__tests__/extendedSchemas.test.ts +50 -0
- package/src/__tests__/membershipDefinitions.test.ts +144 -0
- package/src/__tests__/ticketAdmission.test.ts +73 -0
- package/src/__tests__/utmAttribution.test.ts +118 -0
- package/src/definitions.ts +86 -23
- package/src/extendedSchemas.ts +35 -1
- package/src/index.ts +1 -0
- package/src/sms/smsTemplates.ts +20 -0
- package/src/utils/__tests__/addressUtils.test.ts +176 -0
- package/src/utils/__tests__/apiUtils.test.ts +219 -0
- package/src/utils/__tests__/arrayUtils.test.ts +26 -0
- package/src/utils/__tests__/blogUtils.test.ts +145 -0
- package/src/utils/__tests__/dateTimeUtils.test.ts +233 -0
- package/src/utils/__tests__/discountEngine/discountCalculator.test.ts +410 -0
- package/src/utils/__tests__/generalDateTimeUtils.test.ts +34 -0
- package/src/utils/__tests__/luxonUtils.test.ts +171 -0
- package/src/utils/__tests__/mathUtils.test.ts +30 -0
- package/src/utils/__tests__/objUtils.test.ts +48 -0
- package/src/utils/__tests__/paymentUtils.test.ts +59 -0
- package/src/utils/__tests__/qrCodeUtils.test.ts +28 -1
- package/src/utils/__tests__/reviewUtils.test.ts +65 -0
- package/src/utils/__tests__/slugUtils.test.ts +143 -0
- package/src/utils/__tests__/sortUtils.test.ts +33 -0
- package/src/utils/__tests__/stringUtils.test.ts +37 -0
- package/src/utils/__tests__/ticketListUtils.test.ts +47 -0
- package/src/utils/__tests__/typeUtils.test.ts +12 -0
- package/src/utils/__tests__/userSubscriptionUtils.test.ts +87 -0
- package/src/utils/__tests__/userUtils.test.ts +41 -0
- package/src/utils/__tests__/venueTypeFormatter.test.ts +31 -0
- package/src/utils/service/__tests__/regexUtils.test.ts +66 -0
- package/src/utils/service/__tests__/serviceDBUtils.test.ts +19 -0
- package/src/utils/service/__tests__/serviceFeaturedSortUtils.test.ts +67 -0
- package/src/utils/service/__tests__/serviceUtils.test.ts +190 -0
- package/src/utils/service/serviceFeaturedSortUtils.ts +5 -1
- package/src/utils/ticketListUtils.ts +13 -6
package/src/definitions.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
AgePolicy,
|
|
3
2
|
BashEventType,
|
|
4
3
|
BracketType,
|
|
5
4
|
CompetitionType,
|
|
@@ -18,6 +17,7 @@ import {
|
|
|
18
17
|
User,
|
|
19
18
|
} from "@prisma/client";
|
|
20
19
|
import type {
|
|
20
|
+
AgePolicy as AgePolicyEnum,
|
|
21
21
|
BashPassTier,
|
|
22
22
|
BashEventDressTags,
|
|
23
23
|
BashEventVibeTags,
|
|
@@ -28,6 +28,7 @@ import type {
|
|
|
28
28
|
} from "@prisma/client";
|
|
29
29
|
import {
|
|
30
30
|
CheckoutExt,
|
|
31
|
+
PublicTeaserUser,
|
|
31
32
|
PublicUser,
|
|
32
33
|
ServiceBookingExt,
|
|
33
34
|
type UserExt,
|
|
@@ -79,6 +80,15 @@ export const GovIdRetentionPolicy = {
|
|
|
79
80
|
|
|
80
81
|
export type GovIdRetentionPolicy = GovIdRetentionPolicyEnum;
|
|
81
82
|
|
|
83
|
+
/** Mirrors Prisma `AgePolicy` — `@prisma/client` browser bundle omits runtime enum exports. */
|
|
84
|
+
export const AgePolicy = {
|
|
85
|
+
AllAges: "AllAges",
|
|
86
|
+
EighteenPlus: "EighteenPlus",
|
|
87
|
+
TwentyOnePlus: "TwentyOnePlus",
|
|
88
|
+
} as const satisfies Record<AgePolicyEnum, AgePolicyEnum>;
|
|
89
|
+
|
|
90
|
+
export type AgePolicy = AgePolicyEnum;
|
|
91
|
+
|
|
82
92
|
export const PASSWORD_MIN_LENGTH = 8 as const;
|
|
83
93
|
export const PASSWORD_REQUIREMENTS_REGEX = new RegExp(
|
|
84
94
|
String.raw`^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&^#])[A-Za-z\d@$!%*?&^#]{${PASSWORD_MIN_LENGTH},}$`
|
|
@@ -708,7 +718,7 @@ export interface LoginSession {
|
|
|
708
718
|
}
|
|
709
719
|
|
|
710
720
|
export interface AttendeeOfBashEvent {
|
|
711
|
-
user: PublicUser;
|
|
721
|
+
user: PublicUser | PublicTeaserUser;
|
|
712
722
|
tickets: Ticket[];
|
|
713
723
|
}
|
|
714
724
|
|
|
@@ -1114,7 +1124,6 @@ export const YearsOfExperienceToString: { [key in YearsOfExperienceEnum]: string
|
|
|
1114
1124
|
|
|
1115
1125
|
// Export Prisma enums for use in frontend
|
|
1116
1126
|
export {
|
|
1117
|
-
AgePolicy,
|
|
1118
1127
|
BracketType,
|
|
1119
1128
|
CompetitionType,
|
|
1120
1129
|
EntertainmentServiceType,
|
|
@@ -1481,24 +1490,25 @@ const WHOLE_WORD_BASH_LABEL_PLURAL: ReadonlyMap<string, string> = new Map([
|
|
|
1481
1490
|
]);
|
|
1482
1491
|
|
|
1483
1492
|
function pluralizeBashEventSingularLabel(label: string): string {
|
|
1484
|
-
const
|
|
1493
|
+
const t = label.trim();
|
|
1494
|
+
const manual = BASH_EVENT_SINGULAR_LABEL_TO_PLURAL_SECTION.get(t);
|
|
1485
1495
|
if (manual) return manual;
|
|
1486
1496
|
|
|
1487
|
-
const wholeWord = WHOLE_WORD_BASH_LABEL_PLURAL.get(
|
|
1497
|
+
const wholeWord = WHOLE_WORD_BASH_LABEL_PLURAL.get(t);
|
|
1488
1498
|
if (wholeWord) return wholeWord;
|
|
1489
1499
|
|
|
1490
|
-
if (
|
|
1491
|
-
if (
|
|
1492
|
-
return `${
|
|
1500
|
+
if (t === "Party") return "Parties";
|
|
1501
|
+
if (t.endsWith(" Party")) {
|
|
1502
|
+
return `${t.slice(0, -" Party".length)} Parties`;
|
|
1493
1503
|
}
|
|
1494
|
-
if (
|
|
1495
|
-
return `${
|
|
1504
|
+
if (t.endsWith("-Party")) {
|
|
1505
|
+
return `${t.slice(0, -"-Party".length)}-Parties`;
|
|
1496
1506
|
}
|
|
1497
|
-
if (
|
|
1498
|
-
return `${
|
|
1507
|
+
if (t.endsWith(" Party)")) {
|
|
1508
|
+
return `${t.replace(/ Party\)$/, " Parties)")}`;
|
|
1499
1509
|
}
|
|
1500
|
-
if (
|
|
1501
|
-
return `${
|
|
1510
|
+
if (t.endsWith(" Rave")) {
|
|
1511
|
+
return `${t.slice(0, -" Rave".length)} Raves`;
|
|
1502
1512
|
}
|
|
1503
1513
|
|
|
1504
1514
|
const replacements: ReadonlyArray<[suffix: string, plural: string]> = [
|
|
@@ -1535,8 +1545,8 @@ function pluralizeBashEventSingularLabel(label: string): string {
|
|
|
1535
1545
|
];
|
|
1536
1546
|
|
|
1537
1547
|
for (const [suffix, plural] of replacements) {
|
|
1538
|
-
if (
|
|
1539
|
-
return `${
|
|
1548
|
+
if (t.endsWith(suffix)) {
|
|
1549
|
+
return `${t.slice(0, -suffix.length)}${plural}`;
|
|
1540
1550
|
}
|
|
1541
1551
|
}
|
|
1542
1552
|
|
|
@@ -1547,32 +1557,85 @@ function pluralizeBashEventSingularLabel(label: string): string {
|
|
|
1547
1557
|
// - a future enum value not yet covered above
|
|
1548
1558
|
// For all of these, returning the label verbatim is correct. Appending
|
|
1549
1559
|
// " bashes" produces "Raves bashes" / "Comedy bashes", which reads wrong.
|
|
1550
|
-
return
|
|
1560
|
+
return t;
|
|
1551
1561
|
}
|
|
1552
1562
|
|
|
1553
1563
|
const BASH_EVENT_TYPE_ENUM_VALUES: ReadonlySet<string> = new Set(
|
|
1554
1564
|
Object.values(BashEventType) as string[]
|
|
1555
1565
|
);
|
|
1556
1566
|
|
|
1567
|
+
function resolveCanonicalBashEventTypeKey(raw: string): string | undefined {
|
|
1568
|
+
const t = raw.trim();
|
|
1569
|
+
if (!t) return undefined;
|
|
1570
|
+
if (BASH_EVENT_TYPE_ENUM_VALUES.has(t)) return t;
|
|
1571
|
+
const lower = t.toLowerCase();
|
|
1572
|
+
for (const v of BASH_EVENT_TYPE_ENUM_VALUES) {
|
|
1573
|
+
if (v.toLowerCase() === lower) return v;
|
|
1574
|
+
}
|
|
1575
|
+
return undefined;
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
/**
|
|
1579
|
+
* When the row key matches a `BashEventTypeToString` value (e.g. "House Party")
|
|
1580
|
+
* but not the Prisma enum literal (`HouseParty`), still pluralize like the enum.
|
|
1581
|
+
*/
|
|
1582
|
+
function resolveBashEventEnumKeyFromSingularLabel(raw: string): string | undefined {
|
|
1583
|
+
const t = raw.trim();
|
|
1584
|
+
if (!t) return undefined;
|
|
1585
|
+
const lower = t.toLowerCase();
|
|
1586
|
+
for (const enumKey of BASH_EVENT_TYPE_ENUM_VALUES) {
|
|
1587
|
+
const k = enumKey as BashEventType;
|
|
1588
|
+
const label = BashEventTypeToString[k];
|
|
1589
|
+
if (label === t || label.toLowerCase() === lower) return enumKey;
|
|
1590
|
+
}
|
|
1591
|
+
return undefined;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
/**
|
|
1595
|
+
* Stable row key for homepage/category grouping when `eventType` may be stored
|
|
1596
|
+
* as a Prisma enum literal (e.g. `HouseParty`) or as the singular UI label
|
|
1597
|
+
* (`House Party`).
|
|
1598
|
+
*/
|
|
1599
|
+
export function canonicalBashEventRowKey(raw: string): string {
|
|
1600
|
+
const trimmed = raw.trim();
|
|
1601
|
+
if (!trimmed) return trimmed;
|
|
1602
|
+
const enumKey =
|
|
1603
|
+
resolveCanonicalBashEventTypeKey(trimmed) ??
|
|
1604
|
+
resolveBashEventEnumKeyFromSingularLabel(trimmed);
|
|
1605
|
+
if (enumKey != null) return enumKey;
|
|
1606
|
+
return trimmed;
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1557
1609
|
/**
|
|
1558
1610
|
* Heading shown on the home page row and the `/category/...` page for a bash
|
|
1559
1611
|
* `eventType` / section key. Uses plural-friendly copy for Prisma
|
|
1560
1612
|
* `BashEventType` values; keeps synthetic rows and membership tier rows clear.
|
|
1561
1613
|
*/
|
|
1562
1614
|
export function bashSectionTitleForBashType(bashType: string): string {
|
|
1563
|
-
const
|
|
1615
|
+
const raw = bashType.trim();
|
|
1616
|
+
const lower = raw.toLowerCase();
|
|
1617
|
+
|
|
1618
|
+
const synthetic = SYNTHETIC_BASH_SECTION_TITLE[raw];
|
|
1564
1619
|
if (synthetic != null) return synthetic;
|
|
1620
|
+
if (/\bEvents$/i.test(raw)) return raw;
|
|
1565
1621
|
|
|
1566
|
-
|
|
1567
|
-
|
|
1622
|
+
for (const enumKey of BASH_EVENT_TYPE_ENUM_VALUES) {
|
|
1623
|
+
const singular = BashEventTypeToString[enumKey as BashEventType];
|
|
1624
|
+
const pluralHeading = pluralizeBashEventSingularLabel(singular);
|
|
1625
|
+
if (pluralHeading.toLowerCase() === lower) {
|
|
1626
|
+
return pluralHeading;
|
|
1627
|
+
}
|
|
1568
1628
|
}
|
|
1569
1629
|
|
|
1570
|
-
|
|
1571
|
-
|
|
1630
|
+
const enumKey =
|
|
1631
|
+
resolveCanonicalBashEventTypeKey(raw) ??
|
|
1632
|
+
resolveBashEventEnumKeyFromSingularLabel(raw);
|
|
1633
|
+
if (enumKey != null) {
|
|
1634
|
+
const singular = BashEventTypeToString[enumKey as BashEventType];
|
|
1572
1635
|
return pluralizeBashEventSingularLabel(singular);
|
|
1573
1636
|
}
|
|
1574
1637
|
|
|
1575
|
-
const spaced = insertSpacesInCamelCase(
|
|
1638
|
+
const spaced = insertSpacesInCamelCase(raw);
|
|
1576
1639
|
return pluralizeBashEventSingularLabel(spaced);
|
|
1577
1640
|
}
|
|
1578
1641
|
|
package/src/extendedSchemas.ts
CHANGED
|
@@ -199,6 +199,25 @@ export const FRONT_END_USER_DATA_TO_SELECT = {
|
|
|
199
199
|
},
|
|
200
200
|
} satisfies Prisma.UserSelect;
|
|
201
201
|
|
|
202
|
+
/**
|
|
203
|
+
* Minimal `User` fields for public teaser surfaces (event detail avatars, checkout rows,
|
|
204
|
+
* non-privileged attendee rosters). Omits `email` and other account-level PII.
|
|
205
|
+
*/
|
|
206
|
+
export const PUBLIC_TEASER_USER_DATA_TO_SELECT = {
|
|
207
|
+
id: true,
|
|
208
|
+
username: true,
|
|
209
|
+
givenName: true,
|
|
210
|
+
familyName: true,
|
|
211
|
+
image: true,
|
|
212
|
+
imageUpdatedAt: true,
|
|
213
|
+
uploadedImage: true,
|
|
214
|
+
uploadedImageUpdatedAt: true,
|
|
215
|
+
} satisfies Prisma.UserSelect;
|
|
216
|
+
|
|
217
|
+
export type PublicTeaserUser = Prisma.UserGetPayload<{
|
|
218
|
+
select: typeof PUBLIC_TEASER_USER_DATA_TO_SELECT;
|
|
219
|
+
}>;
|
|
220
|
+
|
|
202
221
|
export const PRIVATE_USER_ACCOUNT_TO_SELECT = {
|
|
203
222
|
...FRONT_END_USER_DATA_TO_SELECT,
|
|
204
223
|
/** Self session only — preferred payment rail (Stripe vs Square). */
|
|
@@ -213,6 +232,8 @@ export const PRIVATE_USER_ACCOUNT_TO_SELECT = {
|
|
|
213
232
|
zipCode: true,
|
|
214
233
|
country: true,
|
|
215
234
|
phone: true,
|
|
235
|
+
/** SMS verification — self account only. */
|
|
236
|
+
phoneVerifiedAt: true,
|
|
216
237
|
membershipExpiresAt: true,
|
|
217
238
|
bashPassStripeSubscriptionId: true,
|
|
218
239
|
bashPassCurrentPeriodEnd: true,
|
|
@@ -1287,7 +1308,8 @@ export type TicketFlexible = Ticket & {
|
|
|
1287
1308
|
};
|
|
1288
1309
|
|
|
1289
1310
|
export interface CheckoutExt extends Checkout {
|
|
1290
|
-
owner
|
|
1311
|
+
/** Full owner row for hosts/organizers; teaser row (no email) for other authenticated viewers. */
|
|
1312
|
+
owner: PublicUser | PublicTeaserUser;
|
|
1291
1313
|
tickets: Ticket[];
|
|
1292
1314
|
}
|
|
1293
1315
|
|
|
@@ -1302,6 +1324,18 @@ export const CHECKOUT_DATA_TO_INCLUDE = {
|
|
|
1302
1324
|
},
|
|
1303
1325
|
} satisfies Prisma.CheckoutInclude;
|
|
1304
1326
|
|
|
1327
|
+
/** Checkout list for non-privileged viewers — buyer email omitted on `owner`. */
|
|
1328
|
+
export const CHECKOUT_DATA_TO_INCLUDE_TEASER_OWNER = {
|
|
1329
|
+
owner: {
|
|
1330
|
+
select: PUBLIC_TEASER_USER_DATA_TO_SELECT,
|
|
1331
|
+
},
|
|
1332
|
+
tickets: {
|
|
1333
|
+
select: {
|
|
1334
|
+
ownerId: true,
|
|
1335
|
+
},
|
|
1336
|
+
},
|
|
1337
|
+
} satisfies Prisma.CheckoutInclude;
|
|
1338
|
+
|
|
1305
1339
|
export interface ReviewExt extends Review {
|
|
1306
1340
|
comments?: BashComment[];
|
|
1307
1341
|
}
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System SMS template keys — bodies are rendered in the API (URLs, env).
|
|
3
|
+
* Consumers use these keys for type-safe `sendTemplatedSms` calls.
|
|
4
|
+
*/
|
|
5
|
+
export const SMS_TEMPLATE_KEYS = [
|
|
6
|
+
"EVENT_REMINDER_1H",
|
|
7
|
+
"EVENT_VENUE_CHANGED",
|
|
8
|
+
"EVENT_WAITLIST_APPROVED",
|
|
9
|
+
"TICKET_CONFIRMED",
|
|
10
|
+
] as const;
|
|
11
|
+
|
|
12
|
+
export type SmsTemplateKey = (typeof SMS_TEMPLATE_KEYS)[number];
|
|
13
|
+
|
|
14
|
+
/** Typed context per template (API maps these to final message strings). */
|
|
15
|
+
export type SmsTemplateContext = {
|
|
16
|
+
EVENT_REMINDER_1H: { eventTitle: string; shortUrl: string };
|
|
17
|
+
EVENT_VENUE_CHANGED: { eventTitle: string; shortUrl: string };
|
|
18
|
+
EVENT_WAITLIST_APPROVED: { eventTitle: string; shortUrl: string };
|
|
19
|
+
TICKET_CONFIRMED: { eventTitle: string; ticketCount: number; ticketsUrl?: string };
|
|
20
|
+
};
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import {
|
|
3
|
+
addressHasEnoughDataForGeolocation,
|
|
4
|
+
addressValuesToDatabaseAddressString,
|
|
5
|
+
databaseAddressStringToAddressValues,
|
|
6
|
+
formatLocalityForCardDisplay,
|
|
7
|
+
databaseAddressStringToOneLineString,
|
|
8
|
+
databaseAddressStringToDisplayString,
|
|
9
|
+
addressToDisplayString,
|
|
10
|
+
extractAddressComponents,
|
|
11
|
+
} from "../addressUtils.js";
|
|
12
|
+
|
|
13
|
+
describe("addressUtils", () => {
|
|
14
|
+
describe("addressHasEnoughDataForGeolocation", () => {
|
|
15
|
+
test("returns true when place, city, and state are set", () => {
|
|
16
|
+
expect(
|
|
17
|
+
addressHasEnoughDataForGeolocation({
|
|
18
|
+
place: "Madison Square Garden",
|
|
19
|
+
city: "New York",
|
|
20
|
+
state: "NY",
|
|
21
|
+
} as any)
|
|
22
|
+
).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("returns true when street, city, and state are set", () => {
|
|
26
|
+
expect(
|
|
27
|
+
addressHasEnoughDataForGeolocation({
|
|
28
|
+
street: "4 Pennsylvania Plaza",
|
|
29
|
+
city: "New York",
|
|
30
|
+
state: "NY",
|
|
31
|
+
} as any)
|
|
32
|
+
).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("returns false when city or state is missing", () => {
|
|
36
|
+
expect(
|
|
37
|
+
addressHasEnoughDataForGeolocation({ place: "Venue", city: "NYC", state: "" } as any)
|
|
38
|
+
).toBe(false);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe("addressValuesToDatabaseAddressString", () => {
|
|
43
|
+
test("joins fields with pipe delimiter", () => {
|
|
44
|
+
expect(
|
|
45
|
+
addressValuesToDatabaseAddressString({
|
|
46
|
+
place: "The Loft",
|
|
47
|
+
street: "123 Main St",
|
|
48
|
+
city: "Brooklyn",
|
|
49
|
+
state: "NY",
|
|
50
|
+
zipCode: "11201",
|
|
51
|
+
country: "USA",
|
|
52
|
+
})
|
|
53
|
+
).toBe("The Loft|123 Main St|Brooklyn|NY|11201|USA");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe("databaseAddressStringToAddressValues", () => {
|
|
58
|
+
test("parses pipe-delimited strings", () => {
|
|
59
|
+
expect(databaseAddressStringToAddressValues("Venue|1 Ave|NYC|NY|10001|USA")).toEqual({
|
|
60
|
+
place: "Venue",
|
|
61
|
+
street: "1 Ave",
|
|
62
|
+
city: "NYC",
|
|
63
|
+
state: "NY",
|
|
64
|
+
zipCode: "10001",
|
|
65
|
+
country: "USA",
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("parses legacy bullet-delimited 5-part strings", () => {
|
|
70
|
+
expect(
|
|
71
|
+
databaseAddressStringToAddressValues("123 Main St • Brooklyn • NY • 11201 • USA")
|
|
72
|
+
).toEqual({
|
|
73
|
+
place: "",
|
|
74
|
+
street: "123 Main St",
|
|
75
|
+
city: "Brooklyn",
|
|
76
|
+
state: "NY",
|
|
77
|
+
zipCode: "11201",
|
|
78
|
+
country: "USA",
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("treats undelimited string as place-only", () => {
|
|
83
|
+
expect(databaseAddressStringToAddressValues("Central Park")).toEqual({
|
|
84
|
+
place: "Central Park",
|
|
85
|
+
street: "",
|
|
86
|
+
city: "",
|
|
87
|
+
state: "",
|
|
88
|
+
zipCode: "",
|
|
89
|
+
country: "",
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("returns empty address for null/undefined", () => {
|
|
94
|
+
expect(databaseAddressStringToAddressValues(null)).toEqual({
|
|
95
|
+
place: "",
|
|
96
|
+
street: "",
|
|
97
|
+
city: "",
|
|
98
|
+
state: "",
|
|
99
|
+
zipCode: "",
|
|
100
|
+
country: "",
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe("formatLocalityForCardDisplay", () => {
|
|
106
|
+
test("joins city, state, and country", () => {
|
|
107
|
+
expect(formatLocalityForCardDisplay("Brooklyn", "NY", "USA")).toBe("Brooklyn, NY, USA");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("skips empty parts", () => {
|
|
111
|
+
expect(formatLocalityForCardDisplay("Austin", null, "USA")).toBe("Austin, USA");
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe("databaseAddressStringToOneLineString", () => {
|
|
116
|
+
test("formats full pipe-delimited address", () => {
|
|
117
|
+
const db = addressValuesToDatabaseAddressString({
|
|
118
|
+
place: "Rooftop Bar",
|
|
119
|
+
street: "99 King St",
|
|
120
|
+
city: "Seattle",
|
|
121
|
+
state: "WA",
|
|
122
|
+
zipCode: "98101",
|
|
123
|
+
country: "USA",
|
|
124
|
+
});
|
|
125
|
+
expect(databaseAddressStringToOneLineString(db)).toBe(
|
|
126
|
+
"Rooftop Bar, 99 King St, Seattle, WA 98101"
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("returns place-only for undelimited strings", () => {
|
|
131
|
+
expect(databaseAddressStringToOneLineString("Secret Warehouse")).toBe("Secret Warehouse");
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe("addressToDisplayString", () => {
|
|
136
|
+
test("builds comma-separated line with zip", () => {
|
|
137
|
+
expect(
|
|
138
|
+
addressToDisplayString({
|
|
139
|
+
place: "Studio",
|
|
140
|
+
street: "5th Ave",
|
|
141
|
+
city: "NYC",
|
|
142
|
+
state: "NY",
|
|
143
|
+
zipCode: "10003",
|
|
144
|
+
country: "USA",
|
|
145
|
+
})
|
|
146
|
+
).toBe("Studio, 5th Ave, NYC, NY 10003");
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
describe("extractAddressComponents", () => {
|
|
151
|
+
test("maps Google place components to IAddress", () => {
|
|
152
|
+
expect(
|
|
153
|
+
extractAddressComponents({
|
|
154
|
+
place_id: "place-123",
|
|
155
|
+
name: "Bash HQ",
|
|
156
|
+
address_components: [
|
|
157
|
+
{ types: ["street_number"], long_name: "100", short_name: "100" },
|
|
158
|
+
{ types: ["route"], long_name: "Broadway", short_name: "Broadway" },
|
|
159
|
+
{ types: ["locality"], long_name: "New York", short_name: "New York" },
|
|
160
|
+
{ types: ["administrative_area_level_1"], long_name: "New York", short_name: "NY" },
|
|
161
|
+
{ types: ["postal_code"], long_name: "10005", short_name: "10005" },
|
|
162
|
+
{ types: ["country"], long_name: "United States", short_name: "US" },
|
|
163
|
+
],
|
|
164
|
+
})
|
|
165
|
+
).toEqual({
|
|
166
|
+
googlePlaceId: "place-123",
|
|
167
|
+
place: "Bash HQ",
|
|
168
|
+
street: "100 Broadway",
|
|
169
|
+
city: "New York",
|
|
170
|
+
state: "NY",
|
|
171
|
+
zipCode: "10005",
|
|
172
|
+
country: "United States",
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
});
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for shared contact/user helpers and environment detection.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test, beforeEach, afterEach } from "@jest/globals";
|
|
6
|
+
import {
|
|
7
|
+
getUserName,
|
|
8
|
+
getUserImage,
|
|
9
|
+
isContactAndNotUser,
|
|
10
|
+
getContactOrUserEmail,
|
|
11
|
+
getUserIdAndNotContactId,
|
|
12
|
+
getBashEventDetailUrlParamsFromBashEvent,
|
|
13
|
+
isProduction,
|
|
14
|
+
} from "../apiUtils.js";
|
|
15
|
+
|
|
16
|
+
describe("apiUtils", () => {
|
|
17
|
+
describe("isContactAndNotUser", () => {
|
|
18
|
+
test("returns true when contactOwnerId is set", () => {
|
|
19
|
+
expect(isContactAndNotUser({ contactOwnerId: "owner-1", fullName: "Jane" })).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("returns false for user-shaped objects", () => {
|
|
23
|
+
expect(isContactAndNotUser({ id: "user-1", email: "jane@example.com" })).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe("getUserName", () => {
|
|
28
|
+
test("returns empty string for undefined", () => {
|
|
29
|
+
expect(getUserName(undefined)).toBe("");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("returns contact fullName when present", () => {
|
|
33
|
+
expect(
|
|
34
|
+
getUserName({ contactOwnerId: "owner-1", fullName: "Jane Contact", contactEmail: "j@x.com" })
|
|
35
|
+
).toBe("Jane Contact");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("falls back to contactEmail for contacts without fullName", () => {
|
|
39
|
+
expect(getUserName({ contactOwnerId: "owner-1", contactEmail: "j@x.com" })).toBe("j@x.com");
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("combines givenName and familyName for users", () => {
|
|
43
|
+
expect(getUserName({ givenName: "Jane", familyName: "Doe", email: "j@x.com" })).toBe("Jane Doe");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("falls back to email when name parts missing", () => {
|
|
47
|
+
expect(getUserName({ email: "solo@example.com" })).toBe("solo@example.com");
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe("getUserImage", () => {
|
|
52
|
+
const noProfilePicture = "/noProfilePicture.svg";
|
|
53
|
+
|
|
54
|
+
test("returns empty string for undefined", () => {
|
|
55
|
+
expect(getUserImage(undefined)).toBe("");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("returns placeholder for contacts", () => {
|
|
59
|
+
expect(getUserImage({ contactOwnerId: "owner-1", fullName: "Jane" })).toBe(noProfilePicture);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("returns uploaded image when only upload exists", () => {
|
|
63
|
+
expect(getUserImage({ uploadedImage: "https://cdn.example/upload.jpg" })).toBe(
|
|
64
|
+
"https://cdn.example/upload.jpg"
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("returns google image when only google image exists", () => {
|
|
69
|
+
expect(getUserImage({ image: "https://lh3.google.com/photo.jpg" })).toBe(
|
|
70
|
+
"https://lh3.google.com/photo.jpg"
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("treats whitespace-only image URLs as missing", () => {
|
|
75
|
+
expect(getUserImage({ uploadedImage: " ", image: "https://google.com/p.jpg" })).toBe(
|
|
76
|
+
"https://google.com/p.jpg"
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("prefers most recently updated image when both exist", () => {
|
|
81
|
+
const older = new Date("2024-01-01");
|
|
82
|
+
const newer = new Date("2024-06-01");
|
|
83
|
+
expect(
|
|
84
|
+
getUserImage({
|
|
85
|
+
uploadedImage: "https://cdn.example/upload.jpg",
|
|
86
|
+
uploadedImageUpdatedAt: newer,
|
|
87
|
+
image: "https://lh3.google.com/photo.jpg",
|
|
88
|
+
imageUpdatedAt: older,
|
|
89
|
+
})
|
|
90
|
+
).toBe("https://cdn.example/upload.jpg");
|
|
91
|
+
expect(
|
|
92
|
+
getUserImage({
|
|
93
|
+
uploadedImage: "https://cdn.example/upload.jpg",
|
|
94
|
+
uploadedImageUpdatedAt: older,
|
|
95
|
+
image: "https://lh3.google.com/photo.jpg",
|
|
96
|
+
imageUpdatedAt: newer,
|
|
97
|
+
})
|
|
98
|
+
).toBe("https://lh3.google.com/photo.jpg");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("falls back to uploadedImage when both exist without timestamps", () => {
|
|
102
|
+
expect(
|
|
103
|
+
getUserImage({
|
|
104
|
+
uploadedImage: "https://cdn.example/upload.jpg",
|
|
105
|
+
image: "https://lh3.google.com/photo.jpg",
|
|
106
|
+
})
|
|
107
|
+
).toBe("https://cdn.example/upload.jpg");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("returns placeholder when user has no images", () => {
|
|
111
|
+
expect(getUserImage({ email: "j@x.com" })).toBe(noProfilePicture);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe("getContactOrUserEmail", () => {
|
|
116
|
+
test("returns contactEmail for contacts", () => {
|
|
117
|
+
expect(getContactOrUserEmail({ contactOwnerId: "o1", contactEmail: "c@x.com" })).toBe("c@x.com");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("returns email for users", () => {
|
|
121
|
+
expect(getContactOrUserEmail({ id: "u1", email: "u@x.com" })).toBe("u@x.com");
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
describe("getUserIdAndNotContactId", () => {
|
|
126
|
+
test("returns null for contacts", () => {
|
|
127
|
+
expect(getUserIdAndNotContactId({ contactOwnerId: "o1" })).toBeNull();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("returns user id for users", () => {
|
|
131
|
+
expect(getUserIdAndNotContactId({ id: "user-42" })).toBe("user-42");
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe("getBashEventDetailUrlParamsFromBashEvent", () => {
|
|
136
|
+
test("returns empty string for undefined event", () => {
|
|
137
|
+
expect(getBashEventDetailUrlParamsFromBashEvent(undefined)).toBe("");
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test("returns empty string when title/desc/cover are absent", () => {
|
|
141
|
+
expect(
|
|
142
|
+
getBashEventDetailUrlParamsFromBashEvent({
|
|
143
|
+
title: "",
|
|
144
|
+
description: null,
|
|
145
|
+
coverPhoto: null,
|
|
146
|
+
} as any)
|
|
147
|
+
).toBe("");
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test("truncates long descriptions before building params", () => {
|
|
151
|
+
const longDesc = "abcdefghijklmnop";
|
|
152
|
+
const result = getBashEventDetailUrlParamsFromBashEvent(
|
|
153
|
+
{ title: "Party", description: longDesc, coverPhoto: null } as any,
|
|
154
|
+
"cover.jpg"
|
|
155
|
+
);
|
|
156
|
+
expect(result).toBe("");
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe("isProduction", () => {
|
|
161
|
+
const envKeys = ["NODE_ENV", "ENVIRONMENT", "BASH_ENV"] as const;
|
|
162
|
+
const saved: Partial<Record<(typeof envKeys)[number], string | undefined>> = {};
|
|
163
|
+
|
|
164
|
+
beforeEach(() => {
|
|
165
|
+
for (const key of envKeys) {
|
|
166
|
+
saved[key] = process.env[key];
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
afterEach(() => {
|
|
171
|
+
for (const key of envKeys) {
|
|
172
|
+
if (saved[key] === undefined) {
|
|
173
|
+
delete process.env[key];
|
|
174
|
+
} else {
|
|
175
|
+
process.env[key] = saved[key];
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test("returns false when ENVIRONMENT contains qa", () => {
|
|
181
|
+
process.env.NODE_ENV = "production";
|
|
182
|
+
process.env.ENVIRONMENT = "qa-staging";
|
|
183
|
+
expect(isProduction()).toBe(false);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test("returns false when BASH_ENV contains qa", () => {
|
|
187
|
+
process.env.NODE_ENV = "production";
|
|
188
|
+
process.env.BASH_ENV = "QA";
|
|
189
|
+
expect(isProduction()).toBe(false);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("returns true only when NODE_ENV is production and env is explicitly production", () => {
|
|
193
|
+
process.env.NODE_ENV = "production";
|
|
194
|
+
process.env.ENVIRONMENT = "production";
|
|
195
|
+
delete process.env.BASH_ENV;
|
|
196
|
+
expect(isProduction()).toBe(true);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test("returns true when BASH_ENV is production", () => {
|
|
200
|
+
process.env.NODE_ENV = "production";
|
|
201
|
+
delete process.env.ENVIRONMENT;
|
|
202
|
+
process.env.BASH_ENV = "production";
|
|
203
|
+
expect(isProduction()).toBe(true);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test("returns false in development even with production env vars", () => {
|
|
207
|
+
process.env.NODE_ENV = "development";
|
|
208
|
+
process.env.ENVIRONMENT = "production";
|
|
209
|
+
expect(isProduction()).toBe(false);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test("returns false when NODE_ENV is production but env vars are unset", () => {
|
|
213
|
+
process.env.NODE_ENV = "production";
|
|
214
|
+
delete process.env.ENVIRONMENT;
|
|
215
|
+
delete process.env.BASH_ENV;
|
|
216
|
+
expect(isProduction()).toBe(false);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
});
|