@getmicdrop/venue-calendar 4.0.87 → 4.0.89
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/{CartView-DrfUvXHU.js → CartView-CvtUTe19.js} +8 -7
- package/dist/CartView-CvtUTe19.js.map +1 -0
- package/dist/{Checkout-BIT0aula.js → Checkout-B6Iqvhz5.js} +3 -3
- package/dist/{Checkout-BIT0aula.js.map → Checkout-B6Iqvhz5.js.map} +1 -1
- package/dist/{Checkout-DNwBnmE3.js → Checkout-l7NYcxer.js} +7 -7
- package/dist/Checkout-l7NYcxer.js.map +1 -0
- package/dist/{CheckoutTimer-C50Ahi93.js → CheckoutTimer-t_De4Cyb.js} +13 -13
- package/dist/CheckoutTimer-t_De4Cyb.js.map +1 -0
- package/dist/{CollectionView-W4Atllhp.js → CollectionView-CbAdxCbJ.js} +5 -5
- package/dist/CollectionView-CbAdxCbJ.js.map +1 -0
- package/dist/{Event-t3hhfFuJ.js → Event-PxIWk8RL.js} +130 -130
- package/dist/Event-PxIWk8RL.js.map +1 -0
- package/dist/{EventPage-CEWppTrK.js → EventPage-C6m9ICd-.js} +7 -7
- package/dist/EventPage-C6m9ICd-.js.map +1 -0
- package/dist/{Heading-DUg5tgzm.js → Heading-RCWgeQcq.js} +2 -2
- package/dist/Heading-RCWgeQcq.js.map +1 -0
- package/dist/{ModalHeader-DEuHuPK2.js → ModalHeader-B4CtYJNc.js} +2 -2
- package/dist/{ModalHeader-DEuHuPK2.js.map → ModalHeader-B4CtYJNc.js.map} +1 -1
- package/dist/{ScarcityBadge-BVM_XAXR.js → ScarcityBadge-CdI_V1gg.js} +11 -11
- package/dist/{ScarcityBadge-BVM_XAXR.js.map → ScarcityBadge-CdI_V1gg.js.map} +1 -1
- package/dist/{SeriesPage-Bg4oZ2fA.js → SeriesPage-7jC1lxOp.js} +5 -5
- package/dist/{SeriesPage-Bg4oZ2fA.js.map → SeriesPage-7jC1lxOp.js.map} +1 -1
- package/dist/Spinner-BEOure61.js +17 -0
- package/dist/Spinner-BEOure61.js.map +1 -0
- package/dist/{Success-DwpMMfeZ.js → Success-CnyCxUxf.js} +7 -7
- package/dist/{Success-DwpMMfeZ.js.map → Success-CnyCxUxf.js.map} +1 -1
- package/dist/{Text-D4lbf8Z6.js → Text-PTp4a7zJ.js} +12 -12
- package/dist/Text-PTp4a7zJ.js.map +1 -0
- package/dist/{VenueCalendar-DYnha5wZ.js → VenueCalendar-CqcmTiwH.js} +3043 -3159
- package/dist/VenueCalendar-CqcmTiwH.js.map +1 -0
- package/dist/{ViewTicketsEmbed-mrawQhqD.js → ViewTicketsEmbed-D1_biEaQ.js} +7 -6
- package/dist/ViewTicketsEmbed-D1_biEaQ.js.map +1 -0
- package/dist/api/api.cjs.map +1 -1
- package/dist/api/api.mjs.map +1 -1
- package/dist/api/types.d.ts +423 -423
- package/dist/{data-toggle-store.svelte-CgH3EfQF.js → data-toggle-store.svelte-DG4WuovC.js} +2 -2
- package/dist/{data-toggle-store.svelte-CgH3EfQF.js.map → data-toggle-store.svelte-DG4WuovC.js.map} +1 -1
- package/dist/{labels-CV4Mq9xD.js → labels-V7Z6TGEH.js} +16 -16
- package/dist/{labels-CV4Mq9xD.js.map → labels-V7Z6TGEH.js.map} +1 -1
- package/dist/seo/types.d.ts +150 -150
- package/dist/{transform-DrAudcCa.js → transform-Bz5QJu_t.js} +2 -2
- package/dist/{transform-DrAudcCa.js.map → transform-Bz5QJu_t.js.map} +1 -1
- package/dist/venue-calendar.css +1 -1
- package/dist/venue-calendar.es.js +10 -10
- package/dist/venue-calendar.iife.js +24 -24
- package/dist/venue-calendar.iife.js.map +1 -1
- package/dist/venue-calendar.umd.js +17 -17
- package/dist/venue-calendar.umd.js.map +1 -1
- package/package.json +2 -2
- package/dist/CartView-DrfUvXHU.js.map +0 -1
- package/dist/Checkout-DNwBnmE3.js.map +0 -1
- package/dist/CheckoutTimer-C50Ahi93.js.map +0 -1
- package/dist/CollectionView-W4Atllhp.js.map +0 -1
- package/dist/Event-t3hhfFuJ.js.map +0 -1
- package/dist/EventPage-CEWppTrK.js.map +0 -1
- package/dist/Heading-DUg5tgzm.js.map +0 -1
- package/dist/Text-D4lbf8Z6.js.map +0 -1
- package/dist/VenueCalendar-DYnha5wZ.js.map +0 -1
- package/dist/ViewTicketsEmbed-mrawQhqD.js.map +0 -1
package/dist/seo/types.d.ts
CHANGED
|
@@ -1,150 +1,150 @@
|
|
|
1
|
-
import { getDefaultTimezone } from '@getmicdrop/svelte-components/utils/timezones';
|
|
2
|
-
/**
|
|
3
|
-
* Input/output TypeScript interfaces for all JSON-LD builders.
|
|
4
|
-
*
|
|
5
|
-
* These describe the data shape each builder expects, NOT the raw API response
|
|
6
|
-
* shape (those exist in `api/types.ts`). The mapping from API types to these
|
|
7
|
-
* builder input types happens at the call site.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
// ---------------------------------------------------------------------------
|
|
11
|
-
// Event builder inputs
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
|
-
|
|
14
|
-
/** What buildEventJsonLd expects for an event. */
|
|
15
|
-
export interface EventJsonLdInput {
|
|
16
|
-
name: string;
|
|
17
|
-
startDateTime: string;
|
|
18
|
-
endDateTime?: string;
|
|
19
|
-
status?: string;
|
|
20
|
-
description?: string;
|
|
21
|
-
eventSummary?: string;
|
|
22
|
-
image?: string;
|
|
23
|
-
coverImage?: string;
|
|
24
|
-
ShowImage?: string;
|
|
25
|
-
availableTickets?: EventTicketInput[];
|
|
26
|
-
performers?: EventPerformerInput[];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface EventTicketInput {
|
|
30
|
-
visibility?: number;
|
|
31
|
-
salesChannel?: number;
|
|
32
|
-
price?: number | string;
|
|
33
|
-
remainingCapacity?: number;
|
|
34
|
-
quantityRemaining?: number;
|
|
35
|
-
quantity?: number;
|
|
36
|
-
soldOut?: boolean;
|
|
37
|
-
salesBegin?: string;
|
|
38
|
-
salesStart?: string;
|
|
39
|
-
saleBegin?: string;
|
|
40
|
-
onSaleStart?: string;
|
|
41
|
-
salesEnd?: string;
|
|
42
|
-
saleEnd?: string;
|
|
43
|
-
onSaleEnd?: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface EventPerformerInput {
|
|
47
|
-
acceptedState?: number;
|
|
48
|
-
shouldBeHidden?: boolean;
|
|
49
|
-
RosterPerformer?: {
|
|
50
|
-
User?: {
|
|
51
|
-
performerProfile?: {
|
|
52
|
-
firstName?: string;
|
|
53
|
-
lastName?: string;
|
|
54
|
-
displayName?: string;
|
|
55
|
-
};
|
|
56
|
-
};
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export interface VenueInput {
|
|
61
|
-
name: string;
|
|
62
|
-
// Discrete postal-address fields from the public resolve payload
|
|
63
|
-
// (PublicVenueInfo). `address` is the street line. Preferred over
|
|
64
|
-
// googleLocationNameCache when a locality signal is present.
|
|
65
|
-
address?: string;
|
|
66
|
-
city?: string;
|
|
67
|
-
state?: string;
|
|
68
|
-
postalCode?: string;
|
|
69
|
-
country?: string;
|
|
70
|
-
googleLocationNameCache?: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface OrganizerInput {
|
|
74
|
-
name: string;
|
|
75
|
-
url?: string;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// ---------------------------------------------------------------------------
|
|
79
|
-
// Series builder inputs (Plan 02)
|
|
80
|
-
// ---------------------------------------------------------------------------
|
|
81
|
-
|
|
82
|
-
/** What buildSeriesJsonLd expects. */
|
|
83
|
-
export interface SeriesJsonLdInput {
|
|
84
|
-
title: string;
|
|
85
|
-
description?: string;
|
|
86
|
-
eventSummary?: string;
|
|
87
|
-
image?: string;
|
|
88
|
-
timeZone: string;
|
|
89
|
-
venue: {
|
|
90
|
-
name: string;
|
|
91
|
-
// Discrete postal-address fields from SeriesVenueDTO (see VenueInput).
|
|
92
|
-
address?: string;
|
|
93
|
-
city?: string;
|
|
94
|
-
state?: string;
|
|
95
|
-
postalCode?: string;
|
|
96
|
-
country?: string;
|
|
97
|
-
googleLocationNameCache?: string;
|
|
98
|
-
};
|
|
99
|
-
performers?: Array<{ displayName: string }>;
|
|
100
|
-
occurrences: Array<{
|
|
101
|
-
id: number;
|
|
102
|
-
title: string;
|
|
103
|
-
slug: string;
|
|
104
|
-
startDateTime: string;
|
|
105
|
-
endDateTime?: string;
|
|
106
|
-
status?: string;
|
|
107
|
-
tickets?: Array<{ name: string; price: number; status: string }>;
|
|
108
|
-
}>;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// ---------------------------------------------------------------------------
|
|
112
|
-
// Collection builder inputs (Plan 02)
|
|
113
|
-
// ---------------------------------------------------------------------------
|
|
114
|
-
|
|
115
|
-
// ---------------------------------------------------------------------------
|
|
116
|
-
// HostSeoController options (Phase 6)
|
|
117
|
-
// ---------------------------------------------------------------------------
|
|
118
|
-
|
|
119
|
-
/** Options for HostSeoController constructor */
|
|
120
|
-
export interface HostSeoControllerOptions {
|
|
121
|
-
/** Venue name for JSON-LD location and page title */
|
|
122
|
-
venueName: string;
|
|
123
|
-
/** Venue address string (from googleLocationNameCache or address field) */
|
|
124
|
-
venueAddress?: string;
|
|
125
|
-
/** Venue timezone (IANA), defaults to getDefaultTimezone() */
|
|
126
|
-
venueTimeZone?: string;
|
|
127
|
-
/** Base URL for canonical links, e.g., "https://comedy-club.com/shows" (defaults to current page URL without query params) */
|
|
128
|
-
baseUrl?: string;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/** What buildCollectionJsonLd expects. */
|
|
132
|
-
export interface CollectionJsonLdInput {
|
|
133
|
-
collectionTitle: string;
|
|
134
|
-
description?: string;
|
|
135
|
-
summary?: string;
|
|
136
|
-
coverImage?: string;
|
|
137
|
-
dateRange?: { startDate: string; endDate: string } | null;
|
|
138
|
-
events: Array<{
|
|
139
|
-
id: number;
|
|
140
|
-
title: string;
|
|
141
|
-
slug?: string;
|
|
142
|
-
startDateTime?: string;
|
|
143
|
-
endDateTime?: string;
|
|
144
|
-
image?: string;
|
|
145
|
-
status?: string;
|
|
146
|
-
venueName?: string;
|
|
147
|
-
venueAddress?: string;
|
|
148
|
-
venueId?: number;
|
|
149
|
-
}>;
|
|
150
|
-
}
|
|
1
|
+
import { getDefaultTimezone } from '@getmicdrop/svelte-components/utils/timezones';
|
|
2
|
+
/**
|
|
3
|
+
* Input/output TypeScript interfaces for all JSON-LD builders.
|
|
4
|
+
*
|
|
5
|
+
* These describe the data shape each builder expects, NOT the raw API response
|
|
6
|
+
* shape (those exist in `api/types.ts`). The mapping from API types to these
|
|
7
|
+
* builder input types happens at the call site.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Event builder inputs
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
/** What buildEventJsonLd expects for an event. */
|
|
15
|
+
export interface EventJsonLdInput {
|
|
16
|
+
name: string;
|
|
17
|
+
startDateTime: string;
|
|
18
|
+
endDateTime?: string;
|
|
19
|
+
status?: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
eventSummary?: string;
|
|
22
|
+
image?: string;
|
|
23
|
+
coverImage?: string;
|
|
24
|
+
ShowImage?: string;
|
|
25
|
+
availableTickets?: EventTicketInput[];
|
|
26
|
+
performers?: EventPerformerInput[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface EventTicketInput {
|
|
30
|
+
visibility?: number;
|
|
31
|
+
salesChannel?: number;
|
|
32
|
+
price?: number | string;
|
|
33
|
+
remainingCapacity?: number;
|
|
34
|
+
quantityRemaining?: number;
|
|
35
|
+
quantity?: number;
|
|
36
|
+
soldOut?: boolean;
|
|
37
|
+
salesBegin?: string;
|
|
38
|
+
salesStart?: string;
|
|
39
|
+
saleBegin?: string;
|
|
40
|
+
onSaleStart?: string;
|
|
41
|
+
salesEnd?: string;
|
|
42
|
+
saleEnd?: string;
|
|
43
|
+
onSaleEnd?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface EventPerformerInput {
|
|
47
|
+
acceptedState?: number;
|
|
48
|
+
shouldBeHidden?: boolean;
|
|
49
|
+
RosterPerformer?: {
|
|
50
|
+
User?: {
|
|
51
|
+
performerProfile?: {
|
|
52
|
+
firstName?: string;
|
|
53
|
+
lastName?: string;
|
|
54
|
+
displayName?: string;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface VenueInput {
|
|
61
|
+
name: string;
|
|
62
|
+
// Discrete postal-address fields from the public resolve payload
|
|
63
|
+
// (PublicVenueInfo). `address` is the street line. Preferred over
|
|
64
|
+
// googleLocationNameCache when a locality signal is present.
|
|
65
|
+
address?: string;
|
|
66
|
+
city?: string;
|
|
67
|
+
state?: string;
|
|
68
|
+
postalCode?: string;
|
|
69
|
+
country?: string;
|
|
70
|
+
googleLocationNameCache?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface OrganizerInput {
|
|
74
|
+
name: string;
|
|
75
|
+
url?: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Series builder inputs (Plan 02)
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
|
|
82
|
+
/** What buildSeriesJsonLd expects. */
|
|
83
|
+
export interface SeriesJsonLdInput {
|
|
84
|
+
title: string;
|
|
85
|
+
description?: string;
|
|
86
|
+
eventSummary?: string;
|
|
87
|
+
image?: string;
|
|
88
|
+
timeZone: string;
|
|
89
|
+
venue: {
|
|
90
|
+
name: string;
|
|
91
|
+
// Discrete postal-address fields from SeriesVenueDTO (see VenueInput).
|
|
92
|
+
address?: string;
|
|
93
|
+
city?: string;
|
|
94
|
+
state?: string;
|
|
95
|
+
postalCode?: string;
|
|
96
|
+
country?: string;
|
|
97
|
+
googleLocationNameCache?: string;
|
|
98
|
+
};
|
|
99
|
+
performers?: Array<{ displayName: string }>;
|
|
100
|
+
occurrences: Array<{
|
|
101
|
+
id: number;
|
|
102
|
+
title: string;
|
|
103
|
+
slug: string;
|
|
104
|
+
startDateTime: string;
|
|
105
|
+
endDateTime?: string;
|
|
106
|
+
status?: string;
|
|
107
|
+
tickets?: Array<{ name: string; price: number; status: string }>;
|
|
108
|
+
}>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// Collection builder inputs (Plan 02)
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
// HostSeoController options (Phase 6)
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
|
|
119
|
+
/** Options for HostSeoController constructor */
|
|
120
|
+
export interface HostSeoControllerOptions {
|
|
121
|
+
/** Venue name for JSON-LD location and page title */
|
|
122
|
+
venueName: string;
|
|
123
|
+
/** Venue address string (from googleLocationNameCache or address field) */
|
|
124
|
+
venueAddress?: string;
|
|
125
|
+
/** Venue timezone (IANA), defaults to getDefaultTimezone() */
|
|
126
|
+
venueTimeZone?: string;
|
|
127
|
+
/** Base URL for canonical links, e.g., "https://comedy-club.com/shows" (defaults to current page URL without query params) */
|
|
128
|
+
baseUrl?: string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** What buildCollectionJsonLd expects. */
|
|
132
|
+
export interface CollectionJsonLdInput {
|
|
133
|
+
collectionTitle: string;
|
|
134
|
+
description?: string;
|
|
135
|
+
summary?: string;
|
|
136
|
+
coverImage?: string;
|
|
137
|
+
dateRange?: { startDate: string; endDate: string } | null;
|
|
138
|
+
events: Array<{
|
|
139
|
+
id: number;
|
|
140
|
+
title: string;
|
|
141
|
+
slug?: string;
|
|
142
|
+
startDateTime?: string;
|
|
143
|
+
endDateTime?: string;
|
|
144
|
+
image?: string;
|
|
145
|
+
status?: string;
|
|
146
|
+
venueName?: string;
|
|
147
|
+
venueAddress?: string;
|
|
148
|
+
venueId?: number;
|
|
149
|
+
}>;
|
|
150
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { aL as D, an as _, aM as P } from "./VenueCalendar-CqcmTiwH.js";
|
|
2
2
|
const q = "https://moxy.sfo3.cdn.digitaloceanspaces.com", A = q;
|
|
3
3
|
function f(t, a = A) {
|
|
4
4
|
return t ? t.startsWith("http://") || t.startsWith("https://") ? t : `${a}${t}` : "";
|
|
@@ -271,4 +271,4 @@ export {
|
|
|
271
271
|
x as b,
|
|
272
272
|
b as t
|
|
273
273
|
};
|
|
274
|
-
//# sourceMappingURL=transform-
|
|
274
|
+
//# sourceMappingURL=transform-Bz5QJu_t.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform-DrAudcCa.js","sources":["../src/lib/utils/imageUrl.ts","../src/lib/api/transformers/address.ts","../src/lib/api/transformers/series.ts","../src/lib/api/transformers/collection.ts","../src/lib/public-calendar-flow/transform.ts"],"sourcesContent":["/**\r\n * Image URL resolution utilities — npm-calendar's local canonical for\r\n * the moxy.sfo3.*.digitaloceanspaces.com CDN base URL. Other modules in\r\n * this package (event-transform, performerDisplay, core/api-client)\r\n * import {@link CDN_BASE_URL} from here rather than re-declaring the\r\n * literal — Phase G ratchet eliminated three duplicate constant\r\n * definitions.\r\n */\r\n\r\n/** Origin (no CDN) — admin / preview surfaces. */\r\nexport const CDN_BASE_URL_ORIGIN = \"https://moxy.sfo3.digitaloceanspaces.com\";\r\n/** CloudFront-fronted CDN — public-facing surfaces. */\r\nexport const CDN_BASE_URL = \"https://moxy.sfo3.cdn.digitaloceanspaces.com\";\r\n/** @deprecated Use {@link CDN_BASE_URL}. Kept as alias during migration. */\r\nconst DEFAULT_CDN_BASE_URL = CDN_BASE_URL;\r\n\r\n/**\r\n * Resolve an image path to a full URL.\r\n * If the path is already a full URL, returns it as-is.\r\n * Otherwise prepends the CDN base URL.\r\n */\r\nexport function getImageUrl(\r\n imagePath: string | null | undefined,\r\n baseUrl: string = DEFAULT_CDN_BASE_URL\r\n): string {\r\n if (!imagePath) return \"\";\r\n\r\n if (imagePath.startsWith(\"http://\") || imagePath.startsWith(\"https://\")) {\r\n return imagePath;\r\n }\r\n\r\n return `${baseUrl}${imagePath}`;\r\n}\r\n","/**\r\n * Address helpers — shared between the event, series and collection page\r\n * transformers.\r\n *\r\n * Lifted verbatim from public-calendar-flow/transform.ts so the series and\r\n * collection canonicals (and the in-place transformApiEvent) read a single\r\n * source instead of each carrying a private copy. Behavior is byte-identical\r\n * to the previous module-private versions.\r\n */\r\n\r\n/**\r\n * Parse a single-line address string into display lines.\r\n * E.g. \"123 Main St, Los Angeles, CA 90012\" -> [\"123 Main St\", \"Los Angeles, CA 90012\"]\r\n */\r\nexport function parseAddress(addressStr: string): string[] {\r\n if (!addressStr) return [];\r\n const parts = addressStr.split(',').map(p => p.trim());\r\n if (parts.length < 2) return [addressStr];\r\n const lastPart = parts[parts.length - 1];\r\n const stateZipMatch = lastPart.match(/^([A-Z]{2})\\s+(\\d{5}(-\\d{4})?)$/);\r\n if (stateZipMatch && parts.length >= 3) {\r\n const state = stateZipMatch[1];\r\n const zip = stateZipMatch[2];\r\n const city = parts[parts.length - 2];\r\n const lines = parts.slice(0, -2);\r\n lines.push(`${city}, ${state} ${zip}`);\r\n return lines;\r\n }\r\n return [parts[0], parts.slice(1).join(', ')];\r\n}\r\n\r\n/**\r\n * Build a Google Maps search URL from an address string.\r\n */\r\nexport function buildGoogleMapsUrl(address: string): string {\r\n if (!address) return '';\r\n return `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(address)}`;\r\n}\r\n","/**\r\n * Series Page Transformer\r\n *\r\n * Wire->domain boundary for the public series page. Maps a SeriesPageData\r\n * payload (from the series API) into the clean EventData shape consumed by\r\n * SeriesPage.svelte / EventExperience (full-width series mode, set via\r\n * eventSeriesId).\r\n *\r\n * Lifted byte-identically from public-calendar-flow/transform.ts's\r\n * transformSeriesPageData. Every ||/?? fallthrough is preserved exactly;\r\n * characterization tests pin the output. transformSeriesPageData now delegates\r\n * here.\r\n *\r\n * COMPOSITION NOTE — why this does NOT reuse parseVenue:\r\n * The api `parseVenue` returns the api-domain `Venue` (raw timezone string,\r\n * fee fields read from the payload). The series page needs the pcf `VenueData`\r\n * shape: timezone is the IANA-RESOLVED zone (getIANATimezone) and the fee\r\n * fields are hard-zeroed (the series payload carries no venue fees). Those\r\n * shapes are not byte-compatible, so the venue sub-shape stays local.\r\n */\r\n\r\nimport { formatDateRaw, getIANATimezone } from '@getmicdrop/svelte-components';\r\nimport { getImageUrl } from '$lib/utils/utils.js';\r\nimport { parseAddress, buildGoogleMapsUrl } from './address.js';\r\nimport type { SeriesPageData } from '../types.js';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n PerformerData,\r\n FAQItem,\r\n SeriesOccurrence,\r\n} from '$lib/public-calendar-flow/types';\r\n\r\n/**\r\n * Transform SeriesPageData (from the series API) into our clean EventData interface.\r\n * Sets eventSeriesId so EventExperience renders in full-width series mode.\r\n */\r\nexport function parseSeries(series: SeriesPageData): EventData {\r\n // Mirror the event transform: raw series carry lowercase `timezone`\r\n // (some PascalCase `timeZone` / snake `time_zone`). Read all casings so a\r\n // non-UTC series doesn't silently fall back to UTC.\r\n const seriesAny = series as SeriesPageData & {\r\n timezone?: string;\r\n time_zone?: string;\r\n };\r\n const timezone = getIANATimezone(\r\n series.timeZone || seriesAny.timezone || seriesAny.time_zone || 'UTC'\r\n );\r\n\r\n // Build image URL\r\n const rawImage = series.image || '';\r\n const imageUrl = rawImage.startsWith('http')\r\n ? rawImage\r\n : rawImage\r\n ? getImageUrl(rawImage)\r\n : '';\r\n\r\n // Map occurrences to SeriesOccurrence[]\r\n const seriesOccurrences: SeriesOccurrence[] = (series.occurrences || []).map(\r\n occ => ({\r\n id: occ.id,\r\n slug: occ.slug || '',\r\n startDateTime: occ.startDateTime,\r\n endDateTime: occ.endDateTime || '',\r\n status: (occ.ctaState?.reason === 'sold_out'\r\n ? 'sold_out'\r\n : 'on_sale') as EventStatus,\r\n ctaText: occ.ctaState?.text || 'Get Tickets',\r\n ctaDisabled: occ.ctaState?.disabled || false,\r\n })\r\n );\r\n\r\n // Use first occurrence for date fields\r\n const firstOcc = series.occurrences?.[0];\r\n let date = '';\r\n if (firstOcc?.startDateTime) {\r\n const dt = new Date(firstOcc.startDateTime);\r\n date = formatDateRaw(\r\n dt,\r\n { timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit' },\r\n 'en-CA'\r\n );\r\n }\r\n\r\n // Map FAQs\r\n const rawFaq = series.venue?.faq;\r\n let faqs: FAQItem[] = [];\r\n if (Array.isArray(rawFaq)) {\r\n faqs = rawFaq.map(f => ({\r\n question: f.question || '',\r\n answer: f.answer || '',\r\n }));\r\n } else if (typeof rawFaq === 'string' && rawFaq) {\r\n faqs = [{ question: 'FAQ', answer: rawFaq }];\r\n }\r\n\r\n // Map performers\r\n const performers: PerformerData[] = (series.performers || []).map(\r\n (p, index) => ({\r\n id: index + 1,\r\n displayName:\r\n p.displayName || [p.firstName, p.lastName].filter(Boolean).join(' '),\r\n profileImage: p.profileImage || undefined,\r\n })\r\n );\r\n\r\n // Venue address\r\n const venueAddress =\r\n series.venue?.location || series.venue?.googleLocationNameCache || '';\r\n\r\n return {\r\n id: series.id,\r\n title: series.title || '',\r\n slug: '',\r\n description: series.description || series.eventSummary || '',\r\n date,\r\n startDateTime: firstOcc?.startDateTime || '',\r\n endDateTime: firstOcc?.endDateTime || '',\r\n doorsOpenTime: '',\r\n timezone,\r\n imageUrl,\r\n venue: {\r\n id: series.venue?.id || 0,\r\n name: series.venue?.name || '',\r\n address: venueAddress,\r\n timezone,\r\n serviceFeePercentage: 0,\r\n serviceFeeCents: 0,\r\n taxPercentage: 0,\r\n },\r\n performers,\r\n tickets: [],\r\n faqs,\r\n disclaimer: series.venue?.disclaimer || undefined,\r\n status: 'on_sale',\r\n eventSeriesId: series.id,\r\n seriesOccurrences,\r\n isPasswordProtected: false,\r\n isRegistrationEvent: false,\r\n totalTicketsRemaining: 0,\r\n totalTicketsCapacity: 0,\r\n venueAddressLines: parseAddress(venueAddress),\r\n googleMapsUrl: buildGoogleMapsUrl(venueAddress),\r\n };\r\n}\r\n\r\n/**\r\n * Back-compat alias — the public-calendar-flow shaper name. Existing call\r\n * sites importing transformSeriesPageData continue to work unchanged.\r\n */\r\nexport const transformSeriesPageData = parseSeries;\r\n","/**\r\n * Collection Page Transformer\r\n *\r\n * Wire->domain boundary for the public collection page. Maps a\r\n * PublicCollectionData payload (from the collection API) into the clean\r\n * EventData shape consumed by CollectionView.svelte / EventExperience\r\n * (full-width collection mode, set via collectionId).\r\n *\r\n * Lifted byte-identically from public-calendar-flow/transform.ts's\r\n * transformCollectionData. Every ||/?? fallthrough is preserved exactly;\r\n * characterization tests pin the output. transformCollectionData now delegates\r\n * here.\r\n *\r\n * COMPOSITION NOTE — why this does NOT reuse parseVenue/parseEvent:\r\n * The collection payload has no venue and no timezone; the EventData it\r\n * produces hard-codes an empty venue and 'UTC'. The per-event mapping is a\r\n * tiny CollectionEvent card shape (id/name/slug/image/startDateTime/status),\r\n * not the full Event domain — reusing parseEvent would change the output.\r\n * Both stay local.\r\n */\r\n\r\nimport { getImageUrl } from '$lib/utils/utils.js';\r\nimport type { PublicCollectionData } from '../types.js';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n CollectionEvent,\r\n} from '$lib/public-calendar-flow/types';\r\n\r\n/**\r\n * Transform PublicCollectionData (from the collection API) into our clean EventData interface.\r\n * Sets collectionId so EventExperience renders in full-width collection mode.\r\n */\r\nexport function parseCollection(collection: PublicCollectionData): EventData {\r\n // Map collection events to CollectionEvent[]\r\n const collectionEvents: CollectionEvent[] = (collection.events || []).map(\r\n ev => {\r\n const rawImg = ev.image || '';\r\n return {\r\n id: ev.id,\r\n name: ev.title || '',\r\n slug: ev.slug || '',\r\n image: rawImg.startsWith('http')\r\n ? rawImg\r\n : rawImg\r\n ? getImageUrl(rawImg)\r\n : '',\r\n startDateTime: ev.startDateTime || '',\r\n status: (ev.status || 'on_sale') as EventStatus,\r\n };\r\n }\r\n );\r\n\r\n // Cover image\r\n const rawCover = collection.coverImage || '';\r\n const imageUrl = rawCover.startsWith('http')\r\n ? rawCover\r\n : rawCover\r\n ? getImageUrl(rawCover)\r\n : '';\r\n\r\n return {\r\n id: collection.id,\r\n title: collection.collectionTitle || '',\r\n slug: '',\r\n description: collection.description || collection.summary || '',\r\n date: '',\r\n startDateTime: '',\r\n endDateTime: '',\r\n doorsOpenTime: '',\r\n timezone: 'UTC',\r\n imageUrl,\r\n venue: {\r\n id: 0,\r\n name: '',\r\n address: '',\r\n timezone: 'UTC',\r\n serviceFeePercentage: 0,\r\n serviceFeeCents: 0,\r\n taxPercentage: 0,\r\n },\r\n performers: [],\r\n tickets: [],\r\n faqs: [],\r\n status: 'on_sale',\r\n collectionId: collection.id,\r\n collectionEvents,\r\n isPasswordProtected: false,\r\n isRegistrationEvent: false,\r\n totalTicketsRemaining: 0,\r\n totalTicketsCapacity: 0,\r\n };\r\n}\r\n\r\n/**\r\n * Back-compat alias — the public-calendar-flow shaper name. Existing call\r\n * sites importing transformCollectionData continue to work unchanged.\r\n */\r\nexport const transformCollectionData = parseCollection;\r\n","import { formatDateRaw, getIANATimezone } from '@getmicdrop/svelte-components';\r\n// Premium Ticket Experience — API → EventData Transformer\r\n// Maps raw API event responses to our clean EventData interface.\r\n// Used when plugging in real API data. The showcase continues using mock-data.ts directly.\r\n\r\nimport { getImageUrl } from '$lib/utils/utils.js';\r\nimport {\r\n parseAddress,\r\n buildGoogleMapsUrl,\r\n} from '$lib/api/transformers/address';\r\n// Canonical wire→domain boundary — all event-level scalar reads go through it.\r\nimport { parseEvent } from '$lib/api/transformers/event';\r\nimport { parseSeries } from '$lib/api/transformers/series';\r\nimport { parseCollection } from '$lib/api/transformers/collection';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n TicketTypeData,\r\n TicketStatus,\r\n VenueData,\r\n PerformerData,\r\n FAQItem,\r\n SeriesOccurrence,\r\n} from './types';\r\nimport type { SeriesPageData, PublicCollectionData } from '$lib/api/types';\r\n\r\n/**\r\n * Map a raw API ticket status/state to our TicketStatus union.\r\n */\r\nfunction mapTicketStatus(ticket: any): TicketStatus {\r\n const now = new Date();\r\n const remaining =\r\n ticket.remainingCapacity ??\r\n ticket.quantityRemaining ??\r\n ticket.quantity ??\r\n 0;\r\n const salesBegin =\r\n ticket.salesBegin ||\r\n ticket.salesStart ||\r\n ticket.saleBegin ||\r\n ticket.onSaleStart;\r\n const salesEnd = ticket.salesEnd || ticket.saleEnd || ticket.onSaleEnd;\r\n\r\n if (remaining <= 0) return 'sold_out';\r\n if (salesEnd && new Date(salesEnd) < now) return 'sales_ended';\r\n if (salesBegin && new Date(salesBegin) > now) return 'coming_soon';\r\n return 'on_sale';\r\n}\r\n\r\n/**\r\n * Map a raw API event status string to our EventStatus union.\r\n */\r\nfunction mapEventStatus(\r\n rawStatus: string,\r\n tickets: TicketTypeData[]\r\n): EventStatus {\r\n const s = (rawStatus || '').toLowerCase().replace(/\\s+/g, '_');\r\n\r\n if (s === 'cancelled' || s === 'canceled') return 'cancelled';\r\n\r\n // Check if event is past based on end time (handled by caller if needed)\r\n if (s === 'past' || s === 'ended') return 'past';\r\n\r\n // MIC-1039: if any hidden ticket is still on sale, the event is \"on_sale\"\r\n // regardless of visible-ticket states — the user just needs a promo code.\r\n // NOTE: this operates on the pcf DOMAIN ticket shape (post-transform, with a\r\n // computed `status` string), NOT the wire shape SC's\r\n // `isHiddenTicketPurchasable` reads (raw visibility/salesChannel/sale-window\r\n // fields). The sale-window math already happened in `mapTicketStatus`, so the\r\n // SC predicate can't honestly serve this site — kept deliberately local.\r\n const hasPurchasableHiddenTickets = tickets.some(\r\n t => t.isHidden && t.status === 'on_sale'\r\n );\r\n if (hasPurchasableHiddenTickets) return 'on_sale';\r\n\r\n // Derive from ticket states\r\n const publicTickets = tickets.filter(t => !t.isHidden);\r\n if (publicTickets.length > 0) {\r\n if (publicTickets.every(t => t.status === 'sold_out')) return 'sold_out';\r\n if (publicTickets.every(t => t.status === 'coming_soon'))\r\n return 'coming_soon';\r\n if (\r\n publicTickets.every(\r\n t => t.status === 'sales_ended' || t.status === 'sold_out'\r\n )\r\n )\r\n return 'sales_ended';\r\n }\r\n\r\n if (s === 'sold_out' || s === 'soldout') return 'sold_out';\r\n if (s === 'coming_soon' || s === 'comingsoon') return 'coming_soon';\r\n if (s === 'sales_ended' || s === 'salesended') return 'sales_ended';\r\n\r\n return 'on_sale';\r\n}\r\n\r\n/**\r\n * Transform a raw API event response into our clean EventData interface.\r\n * This is the bridge between the API and our premium ticket experience components.\r\n *\r\n * COMPOSITION NOTE (events convergence): the wire is parsed ONCE through the\r\n * canonical parseEvent ($lib/api/transformers/event); every event-level\r\n * scalar below projects off the domain Event. Three deliberate wire seams\r\n * remain, characterization-pinned in\r\n * utils/event-shapers.characterization.test.js:\r\n * 1. TICKETS — the TicketTypeData map uses `??` (nullish) semantics over\r\n * raw ticket fields (remainingCapacity/visibility/fee/…) that\r\n * parseTicket's `||`-folding AvailableTicket neither carries nor\r\n * preserves; routing through parseTicket would change rendered output.\r\n * 2. IMAGE — image→imageUrl→image_url precedence intentionally differs\r\n * from the canonical resolver's (imageUrl-first); see the note in\r\n * api/transformers/event.ts.\r\n * 3. VENUE/PERFORMERS — mapped from the raw passthrough objects\r\n * (domain.venue / domain.performers) with B-specific `??` fee/tax\r\n * semantics; the performer canonical lands in PR #260 and should\r\n * absorb the performer map then.\r\n */\r\nexport function transformApiEvent(rawEvent: any): EventData {\r\n // Wire→domain ONCE (see composition note).\r\n const domain = parseEvent(rawEvent);\r\n const rawVenue = domain.venue || {};\r\n // Event-level timeZone is an OPTIONAL per-event override; when absent/blank it\r\n // must inherit the venue timezone. Falling straight to 'UTC' here rendered\r\n // venue-local times (e.g. a Fri 10pm Central show) in UTC (\"Sat 3:00 AM\"),\r\n // which made already-ended events look like future ones.\r\n // (domain.timeZone is the verbatim PascalCase passthrough; domain.timezone\r\n // folds lowercase + snake_case — same chain as before.)\r\n const timezone = getIANATimezone(\r\n domain.timeZone ||\r\n domain.timezone ||\r\n rawVenue.timeZone ||\r\n rawVenue.timezone ||\r\n 'UTC'\r\n );\r\n\r\n // Transform tickets — TICKET SEAM: raw wire tickets by contract (see note).\r\n const rawTickets = rawEvent.availableTickets || [];\r\n const tickets: TicketTypeData[] = rawTickets.map((t: any) => ({\r\n id: t.id || t.ID,\r\n name: t.name || t.title || '',\r\n description: t.description || undefined,\r\n price: t.price ?? 0,\r\n fee: t.fee ?? 0,\r\n quantityAvailable:\r\n t.remainingCapacity ?? t.quantityRemaining ?? t.quantity ?? 0,\r\n quantityTotal: t.totalCapacity ?? t.quantity ?? 0,\r\n minPerOrder: t.minPerOrder ?? t.minQuantity ?? 1,\r\n maxPerOrder: t.maxPerOrder ?? t.maxQuantity ?? 10,\r\n status: mapTicketStatus(t),\r\n salesStartDate:\r\n t.salesBegin || t.salesStart || t.saleBegin || t.onSaleStart || undefined,\r\n salesEndDate: t.salesEnd || t.saleEnd || t.onSaleEnd || undefined,\r\n isDonation: t.type === 2 || t.ticketType === 2 || t.isDonation === true,\r\n isHidden: t.visibility === 2 || t.isHidden === true,\r\n ticketType: t.type || t.ticketType || undefined,\r\n sectionName: t.sectionName || t.section || undefined,\r\n }));\r\n\r\n // Calculate totals from public tickets\r\n const publicTickets = tickets.filter(t => !t.isHidden && !t.isDonation);\r\n const totalRemaining = publicTickets.reduce(\r\n (sum, t) => sum + t.quantityAvailable,\r\n 0\r\n );\r\n const totalCapacity = publicTickets.reduce(\r\n (sum, t) => sum + t.quantityTotal,\r\n 0\r\n );\r\n\r\n // Determine event status\r\n const status = mapEventStatus(domain.status as string, tickets);\r\n\r\n // Build image URL — IMAGE SEAM: image-first precedence (see note).\r\n const rawImage =\r\n rawEvent.image || rawEvent.imageUrl || rawEvent.image_url || '';\r\n const imageUrl = rawImage.startsWith('http')\r\n ? rawImage\r\n : getImageUrl(rawImage);\r\n\r\n // Venue\r\n const venue: VenueData = {\r\n id: rawVenue.id || rawVenue.ID || 0,\r\n name: rawVenue.name || rawVenue.googleLocationNameCache || '',\r\n address: rawVenue.address || rawVenue.googleLocationNameCache || '',\r\n timezone,\r\n serviceFeePercentage: rawVenue.serviceFeePercentage ?? rawVenue.fee ?? 0,\r\n serviceFeeCents: rawVenue.serviceFeeCents ?? 0,\r\n taxPercentage: rawVenue.taxPercentage ?? rawVenue.tax ?? 0,\r\n contactEmail: rawVenue.contactEmail || rawVenue.email || undefined,\r\n };\r\n\r\n // Performers — VENUE/PERFORMERS SEAM: raw passthrough map (see note).\r\n const rawPerformers = domain.performers || [];\r\n const performers: PerformerData[] = rawPerformers.map((p: any) => ({\r\n id: p.id || p.ID,\r\n displayName: p.displayName || p.name || '',\r\n profileImage: p.avatar || p.profileImage || undefined,\r\n role: p.role || undefined,\r\n }));\r\n\r\n // FAQs (may not be in API response)\r\n const faqs: FAQItem[] = (domain.faqs || []).map((f: any) => ({\r\n question: f.question || '',\r\n answer: f.answer || '',\r\n }));\r\n\r\n // Series showtimes → occurrences. A single series-event detail carries a\r\n // `showtimes` array; the v2 <ShowtimeDesigns> renders event.seriesOccurrences\r\n // under \"Upcoming Shows\". Without this map the section is always empty.\r\n const seriesOccurrences: SeriesOccurrence[] = (domain.showtimes || [])\r\n .filter((s: any) => s.published !== false)\r\n .map((s: any, i: number) => ({\r\n id: s.id ?? s.eventId ?? i + 1,\r\n slug: s.slug || '',\r\n startDateTime: s.startDateTime || s.startTime || '',\r\n endDateTime: s.endDateTime || s.endTime || '',\r\n status: (s.ctaState?.reason === 'sold_out'\r\n ? 'sold_out'\r\n : 'on_sale') as EventStatus,\r\n ctaText: s.ctaState?.text || 'Get tickets',\r\n ctaDisabled: s.ctaState?.disabled || false,\r\n }));\r\n\r\n // Date in venue timezone\r\n let date = '';\r\n if (domain.startDateTime) {\r\n const dt = new Date(domain.startDateTime);\r\n date = formatDateRaw(\r\n dt,\r\n { timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit' },\r\n 'en-CA'\r\n );\r\n }\r\n\r\n return {\r\n id: domain.id,\r\n title: domain.title || '',\r\n slug: domain.slug || '',\r\n description: domain.description || domain.eventSummary || '',\r\n date,\r\n startDateTime: domain.startDateTime || '',\r\n endDateTime: domain.endDateTime || '',\r\n doorsOpenTime: domain.doorsOpenTime || '',\r\n timezone,\r\n imageUrl,\r\n venue,\r\n performers,\r\n tickets,\r\n faqs,\r\n disclaimer: domain.disclaimer || undefined,\r\n status,\r\n eventSeriesId: domain.eventSeriesId || undefined,\r\n seriesOccurrences: seriesOccurrences.length ? seriesOccurrences : undefined,\r\n // Public API hides the actual password (json:\"-\") and exposes a boolean\r\n // `hasPassword` flag instead; fall back to a populated `password` for\r\n // admin-shaped payloads.\r\n isPasswordProtected: domain.hasPassword === true || !!domain.password,\r\n isRegistrationEvent:\r\n domain.ticketType === 1 || domain.eventTicketingType === 1,\r\n totalTicketsRemaining: totalRemaining,\r\n totalTicketsCapacity: totalCapacity,\r\n stageName: domain.stage?.name || domain.stageName || undefined,\r\n ageRestriction: domain.ageRestriction || undefined,\r\n displayAgeRestriction: domain.displayAgeRestriction ?? false,\r\n displayStartTime: domain.displayStartTime ?? true,\r\n displayEndTime: domain.displayEndTime ?? true,\r\n displayDoorsTime: domain.displayDoorsTime ?? true,\r\n collectionId: domain.collectionId || undefined, // domain folds collection_id\r\n venueAddressLines: parseAddress(\r\n rawVenue.address || rawVenue.googleLocationNameCache || ''\r\n ),\r\n googleMapsUrl: buildGoogleMapsUrl(\r\n rawVenue.address || rawVenue.googleLocationNameCache || ''\r\n ),\r\n };\r\n}\r\n\r\n/**\r\n * Transform SeriesPageData (from the series API) into our clean EventData interface.\r\n * Sets eventSeriesId so EventExperience renders in full-width series mode.\r\n */\r\nexport function transformSeriesPageData(series: SeriesPageData): EventData {\r\n // Implementation moved to the canonical transformer home\r\n // (`$lib/api/transformers/series.ts`). This export stays as a thin delegate\r\n // so SeriesPage.svelte and other consumers don't churn.\r\n return parseSeries(series);\r\n}\r\n\r\n/**\r\n * Transform PublicCollectionData (from the collection API) into our clean EventData interface.\r\n * Sets collectionId so EventExperience renders in full-width collection mode.\r\n */\r\nexport function transformCollectionData(\r\n collection: PublicCollectionData\r\n): EventData {\r\n // Implementation moved to the canonical transformer home\r\n // (`$lib/api/transformers/collection.ts`). This export stays as a thin\r\n // delegate so CollectionView.svelte and other consumers don't churn.\r\n return parseCollection(collection);\r\n}\r\n"],"names":["CDN_BASE_URL","DEFAULT_CDN_BASE_URL","getImageUrl","imagePath","baseUrl","parseAddress","addressStr","parts","p","stateZipMatch","state","zip","city","lines","buildGoogleMapsUrl","address","parseSeries","series","seriesAny","timezone","getIANATimezone","rawImage","imageUrl","seriesOccurrences","occ","firstOcc","date","dt","formatDateRaw","rawFaq","faqs","f","performers","index","venueAddress","parseCollection","collection","collectionEvents","ev","rawImg","rawCover","mapTicketStatus","ticket","now","remaining","salesBegin","salesEnd","mapEventStatus","rawStatus","tickets","t","publicTickets","transformApiEvent","rawEvent","domain","parseEvent","rawVenue","totalRemaining","sum","totalCapacity","status","venue","s","i","transformSeriesPageData","transformCollectionData"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transform-Bz5QJu_t.js","sources":["../src/lib/utils/imageUrl.ts","../src/lib/api/transformers/address.ts","../src/lib/api/transformers/series.ts","../src/lib/api/transformers/collection.ts","../src/lib/public-calendar-flow/transform.ts"],"sourcesContent":["/**\r\n * Image URL resolution utilities — npm-calendar's local canonical for\r\n * the moxy.sfo3.*.digitaloceanspaces.com CDN base URL. Other modules in\r\n * this package (event-transform, performerDisplay, core/api-client)\r\n * import {@link CDN_BASE_URL} from here rather than re-declaring the\r\n * literal — Phase G ratchet eliminated three duplicate constant\r\n * definitions.\r\n */\r\n\r\n/** Origin (no CDN) — admin / preview surfaces. */\r\nexport const CDN_BASE_URL_ORIGIN = \"https://moxy.sfo3.digitaloceanspaces.com\";\r\n/** CloudFront-fronted CDN — public-facing surfaces. */\r\nexport const CDN_BASE_URL = \"https://moxy.sfo3.cdn.digitaloceanspaces.com\";\r\n/** @deprecated Use {@link CDN_BASE_URL}. Kept as alias during migration. */\r\nconst DEFAULT_CDN_BASE_URL = CDN_BASE_URL;\r\n\r\n/**\r\n * Resolve an image path to a full URL.\r\n * If the path is already a full URL, returns it as-is.\r\n * Otherwise prepends the CDN base URL.\r\n */\r\nexport function getImageUrl(\r\n imagePath: string | null | undefined,\r\n baseUrl: string = DEFAULT_CDN_BASE_URL\r\n): string {\r\n if (!imagePath) return \"\";\r\n\r\n if (imagePath.startsWith(\"http://\") || imagePath.startsWith(\"https://\")) {\r\n return imagePath;\r\n }\r\n\r\n return `${baseUrl}${imagePath}`;\r\n}\r\n","/**\r\n * Address helpers — shared between the event, series and collection page\r\n * transformers.\r\n *\r\n * Lifted verbatim from public-calendar-flow/transform.ts so the series and\r\n * collection canonicals (and the in-place transformApiEvent) read a single\r\n * source instead of each carrying a private copy. Behavior is byte-identical\r\n * to the previous module-private versions.\r\n */\r\n\r\n/**\r\n * Parse a single-line address string into display lines.\r\n * E.g. \"123 Main St, Los Angeles, CA 90012\" -> [\"123 Main St\", \"Los Angeles, CA 90012\"]\r\n */\r\nexport function parseAddress(addressStr: string): string[] {\r\n if (!addressStr) return [];\r\n const parts = addressStr.split(',').map(p => p.trim());\r\n if (parts.length < 2) return [addressStr];\r\n const lastPart = parts[parts.length - 1];\r\n const stateZipMatch = lastPart.match(/^([A-Z]{2})\\s+(\\d{5}(-\\d{4})?)$/);\r\n if (stateZipMatch && parts.length >= 3) {\r\n const state = stateZipMatch[1];\r\n const zip = stateZipMatch[2];\r\n const city = parts[parts.length - 2];\r\n const lines = parts.slice(0, -2);\r\n lines.push(`${city}, ${state} ${zip}`);\r\n return lines;\r\n }\r\n return [parts[0], parts.slice(1).join(', ')];\r\n}\r\n\r\n/**\r\n * Build a Google Maps search URL from an address string.\r\n */\r\nexport function buildGoogleMapsUrl(address: string): string {\r\n if (!address) return '';\r\n return `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(address)}`;\r\n}\r\n","/**\r\n * Series Page Transformer\r\n *\r\n * Wire->domain boundary for the public series page. Maps a SeriesPageData\r\n * payload (from the series API) into the clean EventData shape consumed by\r\n * SeriesPage.svelte / EventExperience (full-width series mode, set via\r\n * eventSeriesId).\r\n *\r\n * Lifted byte-identically from public-calendar-flow/transform.ts's\r\n * transformSeriesPageData. Every ||/?? fallthrough is preserved exactly;\r\n * characterization tests pin the output. transformSeriesPageData now delegates\r\n * here.\r\n *\r\n * COMPOSITION NOTE — why this does NOT reuse parseVenue:\r\n * The api `parseVenue` returns the api-domain `Venue` (raw timezone string,\r\n * fee fields read from the payload). The series page needs the pcf `VenueData`\r\n * shape: timezone is the IANA-RESOLVED zone (getIANATimezone) and the fee\r\n * fields are hard-zeroed (the series payload carries no venue fees). Those\r\n * shapes are not byte-compatible, so the venue sub-shape stays local.\r\n */\r\n\r\nimport { formatDateRaw, getIANATimezone } from '@getmicdrop/svelte-components';\r\nimport { getImageUrl } from '$lib/utils/utils.js';\r\nimport { parseAddress, buildGoogleMapsUrl } from './address.js';\r\nimport type { SeriesPageData } from '../types.js';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n PerformerData,\r\n FAQItem,\r\n SeriesOccurrence,\r\n} from '$lib/public-calendar-flow/types';\r\n\r\n/**\r\n * Transform SeriesPageData (from the series API) into our clean EventData interface.\r\n * Sets eventSeriesId so EventExperience renders in full-width series mode.\r\n */\r\nexport function parseSeries(series: SeriesPageData): EventData {\r\n // Mirror the event transform: raw series carry lowercase `timezone`\r\n // (some PascalCase `timeZone` / snake `time_zone`). Read all casings so a\r\n // non-UTC series doesn't silently fall back to UTC.\r\n const seriesAny = series as SeriesPageData & {\r\n timezone?: string;\r\n time_zone?: string;\r\n };\r\n const timezone = getIANATimezone(\r\n series.timeZone || seriesAny.timezone || seriesAny.time_zone || 'UTC'\r\n );\r\n\r\n // Build image URL\r\n const rawImage = series.image || '';\r\n const imageUrl = rawImage.startsWith('http')\r\n ? rawImage\r\n : rawImage\r\n ? getImageUrl(rawImage)\r\n : '';\r\n\r\n // Map occurrences to SeriesOccurrence[]\r\n const seriesOccurrences: SeriesOccurrence[] = (series.occurrences || []).map(\r\n occ => ({\r\n id: occ.id,\r\n slug: occ.slug || '',\r\n startDateTime: occ.startDateTime,\r\n endDateTime: occ.endDateTime || '',\r\n status: (occ.ctaState?.reason === 'sold_out'\r\n ? 'sold_out'\r\n : 'on_sale') as EventStatus,\r\n ctaText: occ.ctaState?.text || 'Get Tickets',\r\n ctaDisabled: occ.ctaState?.disabled || false,\r\n })\r\n );\r\n\r\n // Use first occurrence for date fields\r\n const firstOcc = series.occurrences?.[0];\r\n let date = '';\r\n if (firstOcc?.startDateTime) {\r\n const dt = new Date(firstOcc.startDateTime);\r\n date = formatDateRaw(\r\n dt,\r\n { timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit' },\r\n 'en-CA'\r\n );\r\n }\r\n\r\n // Map FAQs\r\n const rawFaq = series.venue?.faq;\r\n let faqs: FAQItem[] = [];\r\n if (Array.isArray(rawFaq)) {\r\n faqs = rawFaq.map(f => ({\r\n question: f.question || '',\r\n answer: f.answer || '',\r\n }));\r\n } else if (typeof rawFaq === 'string' && rawFaq) {\r\n faqs = [{ question: 'FAQ', answer: rawFaq }];\r\n }\r\n\r\n // Map performers\r\n const performers: PerformerData[] = (series.performers || []).map(\r\n (p, index) => ({\r\n id: index + 1,\r\n displayName:\r\n p.displayName || [p.firstName, p.lastName].filter(Boolean).join(' '),\r\n profileImage: p.profileImage || undefined,\r\n })\r\n );\r\n\r\n // Venue address\r\n const venueAddress =\r\n series.venue?.location || series.venue?.googleLocationNameCache || '';\r\n\r\n return {\r\n id: series.id,\r\n title: series.title || '',\r\n slug: '',\r\n description: series.description || series.eventSummary || '',\r\n date,\r\n startDateTime: firstOcc?.startDateTime || '',\r\n endDateTime: firstOcc?.endDateTime || '',\r\n doorsOpenTime: '',\r\n timezone,\r\n imageUrl,\r\n venue: {\r\n id: series.venue?.id || 0,\r\n name: series.venue?.name || '',\r\n address: venueAddress,\r\n timezone,\r\n serviceFeePercentage: 0,\r\n serviceFeeCents: 0,\r\n taxPercentage: 0,\r\n },\r\n performers,\r\n tickets: [],\r\n faqs,\r\n disclaimer: series.venue?.disclaimer || undefined,\r\n status: 'on_sale',\r\n eventSeriesId: series.id,\r\n seriesOccurrences,\r\n isPasswordProtected: false,\r\n isRegistrationEvent: false,\r\n totalTicketsRemaining: 0,\r\n totalTicketsCapacity: 0,\r\n venueAddressLines: parseAddress(venueAddress),\r\n googleMapsUrl: buildGoogleMapsUrl(venueAddress),\r\n };\r\n}\r\n\r\n/**\r\n * Back-compat alias — the public-calendar-flow shaper name. Existing call\r\n * sites importing transformSeriesPageData continue to work unchanged.\r\n */\r\nexport const transformSeriesPageData = parseSeries;\r\n","/**\r\n * Collection Page Transformer\r\n *\r\n * Wire->domain boundary for the public collection page. Maps a\r\n * PublicCollectionData payload (from the collection API) into the clean\r\n * EventData shape consumed by CollectionView.svelte / EventExperience\r\n * (full-width collection mode, set via collectionId).\r\n *\r\n * Lifted byte-identically from public-calendar-flow/transform.ts's\r\n * transformCollectionData. Every ||/?? fallthrough is preserved exactly;\r\n * characterization tests pin the output. transformCollectionData now delegates\r\n * here.\r\n *\r\n * COMPOSITION NOTE — why this does NOT reuse parseVenue/parseEvent:\r\n * The collection payload has no venue and no timezone; the EventData it\r\n * produces hard-codes an empty venue and 'UTC'. The per-event mapping is a\r\n * tiny CollectionEvent card shape (id/name/slug/image/startDateTime/status),\r\n * not the full Event domain — reusing parseEvent would change the output.\r\n * Both stay local.\r\n */\r\n\r\nimport { getImageUrl } from '$lib/utils/utils.js';\r\nimport type { PublicCollectionData } from '../types.js';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n CollectionEvent,\r\n} from '$lib/public-calendar-flow/types';\r\n\r\n/**\r\n * Transform PublicCollectionData (from the collection API) into our clean EventData interface.\r\n * Sets collectionId so EventExperience renders in full-width collection mode.\r\n */\r\nexport function parseCollection(collection: PublicCollectionData): EventData {\r\n // Map collection events to CollectionEvent[]\r\n const collectionEvents: CollectionEvent[] = (collection.events || []).map(\r\n ev => {\r\n const rawImg = ev.image || '';\r\n return {\r\n id: ev.id,\r\n name: ev.title || '',\r\n slug: ev.slug || '',\r\n image: rawImg.startsWith('http')\r\n ? rawImg\r\n : rawImg\r\n ? getImageUrl(rawImg)\r\n : '',\r\n startDateTime: ev.startDateTime || '',\r\n status: (ev.status || 'on_sale') as EventStatus,\r\n };\r\n }\r\n );\r\n\r\n // Cover image\r\n const rawCover = collection.coverImage || '';\r\n const imageUrl = rawCover.startsWith('http')\r\n ? rawCover\r\n : rawCover\r\n ? getImageUrl(rawCover)\r\n : '';\r\n\r\n return {\r\n id: collection.id,\r\n title: collection.collectionTitle || '',\r\n slug: '',\r\n description: collection.description || collection.summary || '',\r\n date: '',\r\n startDateTime: '',\r\n endDateTime: '',\r\n doorsOpenTime: '',\r\n timezone: 'UTC',\r\n imageUrl,\r\n venue: {\r\n id: 0,\r\n name: '',\r\n address: '',\r\n timezone: 'UTC',\r\n serviceFeePercentage: 0,\r\n serviceFeeCents: 0,\r\n taxPercentage: 0,\r\n },\r\n performers: [],\r\n tickets: [],\r\n faqs: [],\r\n status: 'on_sale',\r\n collectionId: collection.id,\r\n collectionEvents,\r\n isPasswordProtected: false,\r\n isRegistrationEvent: false,\r\n totalTicketsRemaining: 0,\r\n totalTicketsCapacity: 0,\r\n };\r\n}\r\n\r\n/**\r\n * Back-compat alias — the public-calendar-flow shaper name. Existing call\r\n * sites importing transformCollectionData continue to work unchanged.\r\n */\r\nexport const transformCollectionData = parseCollection;\r\n","import { formatDateRaw, getIANATimezone } from '@getmicdrop/svelte-components';\r\n// Premium Ticket Experience — API → EventData Transformer\r\n// Maps raw API event responses to our clean EventData interface.\r\n// Used when plugging in real API data. The showcase continues using mock-data.ts directly.\r\n\r\nimport { getImageUrl } from '$lib/utils/utils.js';\r\nimport {\r\n parseAddress,\r\n buildGoogleMapsUrl,\r\n} from '$lib/api/transformers/address';\r\n// Canonical wire→domain boundary — all event-level scalar reads go through it.\r\nimport { parseEvent } from '$lib/api/transformers/event';\r\nimport { parseSeries } from '$lib/api/transformers/series';\r\nimport { parseCollection } from '$lib/api/transformers/collection';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n TicketTypeData,\r\n TicketStatus,\r\n VenueData,\r\n PerformerData,\r\n FAQItem,\r\n SeriesOccurrence,\r\n} from './types';\r\nimport type { SeriesPageData, PublicCollectionData } from '$lib/api/types';\r\n\r\n/**\r\n * Map a raw API ticket status/state to our TicketStatus union.\r\n */\r\nfunction mapTicketStatus(ticket: any): TicketStatus {\r\n const now = new Date();\r\n const remaining =\r\n ticket.remainingCapacity ??\r\n ticket.quantityRemaining ??\r\n ticket.quantity ??\r\n 0;\r\n const salesBegin =\r\n ticket.salesBegin ||\r\n ticket.salesStart ||\r\n ticket.saleBegin ||\r\n ticket.onSaleStart;\r\n const salesEnd = ticket.salesEnd || ticket.saleEnd || ticket.onSaleEnd;\r\n\r\n if (remaining <= 0) return 'sold_out';\r\n if (salesEnd && new Date(salesEnd) < now) return 'sales_ended';\r\n if (salesBegin && new Date(salesBegin) > now) return 'coming_soon';\r\n return 'on_sale';\r\n}\r\n\r\n/**\r\n * Map a raw API event status string to our EventStatus union.\r\n */\r\nfunction mapEventStatus(\r\n rawStatus: string,\r\n tickets: TicketTypeData[]\r\n): EventStatus {\r\n const s = (rawStatus || '').toLowerCase().replace(/\\s+/g, '_');\r\n\r\n if (s === 'cancelled' || s === 'canceled') return 'cancelled';\r\n\r\n // Check if event is past based on end time (handled by caller if needed)\r\n if (s === 'past' || s === 'ended') return 'past';\r\n\r\n // MIC-1039: if any hidden ticket is still on sale, the event is \"on_sale\"\r\n // regardless of visible-ticket states — the user just needs a promo code.\r\n // NOTE: this operates on the pcf DOMAIN ticket shape (post-transform, with a\r\n // computed `status` string), NOT the wire shape SC's\r\n // `isHiddenTicketPurchasable` reads (raw visibility/salesChannel/sale-window\r\n // fields). The sale-window math already happened in `mapTicketStatus`, so the\r\n // SC predicate can't honestly serve this site — kept deliberately local.\r\n const hasPurchasableHiddenTickets = tickets.some(\r\n t => t.isHidden && t.status === 'on_sale'\r\n );\r\n if (hasPurchasableHiddenTickets) return 'on_sale';\r\n\r\n // Derive from ticket states\r\n const publicTickets = tickets.filter(t => !t.isHidden);\r\n if (publicTickets.length > 0) {\r\n if (publicTickets.every(t => t.status === 'sold_out')) return 'sold_out';\r\n if (publicTickets.every(t => t.status === 'coming_soon'))\r\n return 'coming_soon';\r\n if (\r\n publicTickets.every(\r\n t => t.status === 'sales_ended' || t.status === 'sold_out'\r\n )\r\n )\r\n return 'sales_ended';\r\n }\r\n\r\n if (s === 'sold_out' || s === 'soldout') return 'sold_out';\r\n if (s === 'coming_soon' || s === 'comingsoon') return 'coming_soon';\r\n if (s === 'sales_ended' || s === 'salesended') return 'sales_ended';\r\n\r\n return 'on_sale';\r\n}\r\n\r\n/**\r\n * Transform a raw API event response into our clean EventData interface.\r\n * This is the bridge between the API and our premium ticket experience components.\r\n *\r\n * COMPOSITION NOTE (events convergence): the wire is parsed ONCE through the\r\n * canonical parseEvent ($lib/api/transformers/event); every event-level\r\n * scalar below projects off the domain Event. Three deliberate wire seams\r\n * remain, characterization-pinned in\r\n * utils/event-shapers.characterization.test.js:\r\n * 1. TICKETS — the TicketTypeData map uses `??` (nullish) semantics over\r\n * raw ticket fields (remainingCapacity/visibility/fee/…) that\r\n * parseTicket's `||`-folding AvailableTicket neither carries nor\r\n * preserves; routing through parseTicket would change rendered output.\r\n * 2. IMAGE — image→imageUrl→image_url precedence intentionally differs\r\n * from the canonical resolver's (imageUrl-first); see the note in\r\n * api/transformers/event.ts.\r\n * 3. VENUE/PERFORMERS — mapped from the raw passthrough objects\r\n * (domain.venue / domain.performers) with B-specific `??` fee/tax\r\n * semantics; the performer canonical lands in PR #260 and should\r\n * absorb the performer map then.\r\n */\r\nexport function transformApiEvent(rawEvent: any): EventData {\r\n // Wire→domain ONCE (see composition note).\r\n const domain = parseEvent(rawEvent);\r\n const rawVenue = domain.venue || {};\r\n // Event-level timeZone is an OPTIONAL per-event override; when absent/blank it\r\n // must inherit the venue timezone. Falling straight to 'UTC' here rendered\r\n // venue-local times (e.g. a Fri 10pm Central show) in UTC (\"Sat 3:00 AM\"),\r\n // which made already-ended events look like future ones.\r\n // (domain.timeZone is the verbatim PascalCase passthrough; domain.timezone\r\n // folds lowercase + snake_case — same chain as before.)\r\n const timezone = getIANATimezone(\r\n domain.timeZone ||\r\n domain.timezone ||\r\n rawVenue.timeZone ||\r\n rawVenue.timezone ||\r\n 'UTC'\r\n );\r\n\r\n // Transform tickets — TICKET SEAM: raw wire tickets by contract (see note).\r\n const rawTickets = rawEvent.availableTickets || [];\r\n const tickets: TicketTypeData[] = rawTickets.map((t: any) => ({\r\n id: t.id || t.ID,\r\n name: t.name || t.title || '',\r\n description: t.description || undefined,\r\n price: t.price ?? 0,\r\n fee: t.fee ?? 0,\r\n quantityAvailable:\r\n t.remainingCapacity ?? t.quantityRemaining ?? t.quantity ?? 0,\r\n quantityTotal: t.totalCapacity ?? t.quantity ?? 0,\r\n minPerOrder: t.minPerOrder ?? t.minQuantity ?? 1,\r\n maxPerOrder: t.maxPerOrder ?? t.maxQuantity ?? 10,\r\n status: mapTicketStatus(t),\r\n salesStartDate:\r\n t.salesBegin || t.salesStart || t.saleBegin || t.onSaleStart || undefined,\r\n salesEndDate: t.salesEnd || t.saleEnd || t.onSaleEnd || undefined,\r\n isDonation: t.type === 2 || t.ticketType === 2 || t.isDonation === true,\r\n isHidden: t.visibility === 2 || t.isHidden === true,\r\n ticketType: t.type || t.ticketType || undefined,\r\n sectionName: t.sectionName || t.section || undefined,\r\n }));\r\n\r\n // Calculate totals from public tickets\r\n const publicTickets = tickets.filter(t => !t.isHidden && !t.isDonation);\r\n const totalRemaining = publicTickets.reduce(\r\n (sum, t) => sum + t.quantityAvailable,\r\n 0\r\n );\r\n const totalCapacity = publicTickets.reduce(\r\n (sum, t) => sum + t.quantityTotal,\r\n 0\r\n );\r\n\r\n // Determine event status\r\n const status = mapEventStatus(domain.status as string, tickets);\r\n\r\n // Build image URL — IMAGE SEAM: image-first precedence (see note).\r\n const rawImage =\r\n rawEvent.image || rawEvent.imageUrl || rawEvent.image_url || '';\r\n const imageUrl = rawImage.startsWith('http')\r\n ? rawImage\r\n : getImageUrl(rawImage);\r\n\r\n // Venue\r\n const venue: VenueData = {\r\n id: rawVenue.id || rawVenue.ID || 0,\r\n name: rawVenue.name || rawVenue.googleLocationNameCache || '',\r\n address: rawVenue.address || rawVenue.googleLocationNameCache || '',\r\n timezone,\r\n serviceFeePercentage: rawVenue.serviceFeePercentage ?? rawVenue.fee ?? 0,\r\n serviceFeeCents: rawVenue.serviceFeeCents ?? 0,\r\n taxPercentage: rawVenue.taxPercentage ?? rawVenue.tax ?? 0,\r\n contactEmail: rawVenue.contactEmail || rawVenue.email || undefined,\r\n };\r\n\r\n // Performers — VENUE/PERFORMERS SEAM: raw passthrough map (see note).\r\n const rawPerformers = domain.performers || [];\r\n const performers: PerformerData[] = rawPerformers.map((p: any) => ({\r\n id: p.id || p.ID,\r\n displayName: p.displayName || p.name || '',\r\n profileImage: p.avatar || p.profileImage || undefined,\r\n role: p.role || undefined,\r\n }));\r\n\r\n // FAQs (may not be in API response)\r\n const faqs: FAQItem[] = (domain.faqs || []).map((f: any) => ({\r\n question: f.question || '',\r\n answer: f.answer || '',\r\n }));\r\n\r\n // Series showtimes → occurrences. A single series-event detail carries a\r\n // `showtimes` array; the v2 <ShowtimeDesigns> renders event.seriesOccurrences\r\n // under \"Upcoming Shows\". Without this map the section is always empty.\r\n const seriesOccurrences: SeriesOccurrence[] = (domain.showtimes || [])\r\n .filter((s: any) => s.published !== false)\r\n .map((s: any, i: number) => ({\r\n id: s.id ?? s.eventId ?? i + 1,\r\n slug: s.slug || '',\r\n startDateTime: s.startDateTime || s.startTime || '',\r\n endDateTime: s.endDateTime || s.endTime || '',\r\n status: (s.ctaState?.reason === 'sold_out'\r\n ? 'sold_out'\r\n : 'on_sale') as EventStatus,\r\n ctaText: s.ctaState?.text || 'Get tickets',\r\n ctaDisabled: s.ctaState?.disabled || false,\r\n }));\r\n\r\n // Date in venue timezone\r\n let date = '';\r\n if (domain.startDateTime) {\r\n const dt = new Date(domain.startDateTime);\r\n date = formatDateRaw(\r\n dt,\r\n { timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit' },\r\n 'en-CA'\r\n );\r\n }\r\n\r\n return {\r\n id: domain.id,\r\n title: domain.title || '',\r\n slug: domain.slug || '',\r\n description: domain.description || domain.eventSummary || '',\r\n date,\r\n startDateTime: domain.startDateTime || '',\r\n endDateTime: domain.endDateTime || '',\r\n doorsOpenTime: domain.doorsOpenTime || '',\r\n timezone,\r\n imageUrl,\r\n venue,\r\n performers,\r\n tickets,\r\n faqs,\r\n disclaimer: domain.disclaimer || undefined,\r\n status,\r\n eventSeriesId: domain.eventSeriesId || undefined,\r\n seriesOccurrences: seriesOccurrences.length ? seriesOccurrences : undefined,\r\n // Public API hides the actual password (json:\"-\") and exposes a boolean\r\n // `hasPassword` flag instead; fall back to a populated `password` for\r\n // admin-shaped payloads.\r\n isPasswordProtected: domain.hasPassword === true || !!domain.password,\r\n isRegistrationEvent:\r\n domain.ticketType === 1 || domain.eventTicketingType === 1,\r\n totalTicketsRemaining: totalRemaining,\r\n totalTicketsCapacity: totalCapacity,\r\n stageName: domain.stage?.name || domain.stageName || undefined,\r\n ageRestriction: domain.ageRestriction || undefined,\r\n displayAgeRestriction: domain.displayAgeRestriction ?? false,\r\n displayStartTime: domain.displayStartTime ?? true,\r\n displayEndTime: domain.displayEndTime ?? true,\r\n displayDoorsTime: domain.displayDoorsTime ?? true,\r\n collectionId: domain.collectionId || undefined, // domain folds collection_id\r\n venueAddressLines: parseAddress(\r\n rawVenue.address || rawVenue.googleLocationNameCache || ''\r\n ),\r\n googleMapsUrl: buildGoogleMapsUrl(\r\n rawVenue.address || rawVenue.googleLocationNameCache || ''\r\n ),\r\n };\r\n}\r\n\r\n/**\r\n * Transform SeriesPageData (from the series API) into our clean EventData interface.\r\n * Sets eventSeriesId so EventExperience renders in full-width series mode.\r\n */\r\nexport function transformSeriesPageData(series: SeriesPageData): EventData {\r\n // Implementation moved to the canonical transformer home\r\n // (`$lib/api/transformers/series.ts`). This export stays as a thin delegate\r\n // so SeriesPage.svelte and other consumers don't churn.\r\n return parseSeries(series);\r\n}\r\n\r\n/**\r\n * Transform PublicCollectionData (from the collection API) into our clean EventData interface.\r\n * Sets collectionId so EventExperience renders in full-width collection mode.\r\n */\r\nexport function transformCollectionData(\r\n collection: PublicCollectionData\r\n): EventData {\r\n // Implementation moved to the canonical transformer home\r\n // (`$lib/api/transformers/collection.ts`). This export stays as a thin\r\n // delegate so CollectionView.svelte and other consumers don't churn.\r\n return parseCollection(collection);\r\n}\r\n"],"names":["CDN_BASE_URL","DEFAULT_CDN_BASE_URL","getImageUrl","imagePath","baseUrl","parseAddress","addressStr","parts","p","stateZipMatch","state","zip","city","lines","buildGoogleMapsUrl","address","parseSeries","series","seriesAny","timezone","getIANATimezone","rawImage","imageUrl","seriesOccurrences","occ","firstOcc","date","dt","formatDateRaw","rawFaq","faqs","f","performers","index","venueAddress","parseCollection","collection","collectionEvents","ev","rawImg","rawCover","mapTicketStatus","ticket","now","remaining","salesBegin","salesEnd","mapEventStatus","rawStatus","tickets","t","publicTickets","transformApiEvent","rawEvent","domain","parseEvent","rawVenue","totalRemaining","sum","totalCapacity","status","venue","s","i","transformSeriesPageData","transformCollectionData"],"mappings":"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"}
|