@voyantjs/octo 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,215 @@
1
+ export function toIsoString(value) {
2
+ return value ? value.toISOString() : null;
3
+ }
4
+ export function formatLocalDateTime(value, timeZone) {
5
+ const parts = new Intl.DateTimeFormat("en-GB", {
6
+ timeZone,
7
+ hour12: false,
8
+ year: "numeric",
9
+ month: "2-digit",
10
+ day: "2-digit",
11
+ hour: "2-digit",
12
+ minute: "2-digit",
13
+ second: "2-digit",
14
+ }).formatToParts(value);
15
+ const lookup = Object.fromEntries(parts.map((part) => [part.type, part.value]));
16
+ return `${lookup.year}-${lookup.month}-${lookup.day}T${lookup.hour}:${lookup.minute}:${lookup.second}`;
17
+ }
18
+ export function inferOctoAvailabilityType(bookingMode) {
19
+ return bookingMode === "open" ? "OPENING_HOURS" : "START_TIME";
20
+ }
21
+ export function inferOctoUnitType(unit) {
22
+ const haystack = `${unit.code ?? ""} ${unit.name}`.toLowerCase();
23
+ if (haystack.includes("adult"))
24
+ return "ADULT";
25
+ if (haystack.includes("child"))
26
+ return "CHILD";
27
+ if (haystack.includes("youth") || haystack.includes("teen"))
28
+ return "YOUTH";
29
+ if (haystack.includes("infant") || haystack.includes("baby"))
30
+ return "INFANT";
31
+ if (haystack.includes("family"))
32
+ return "FAMILY";
33
+ if (haystack.includes("senior"))
34
+ return "SENIOR";
35
+ if (haystack.includes("student"))
36
+ return "STUDENT";
37
+ if (haystack.includes("military"))
38
+ return "MILITARY";
39
+ return unit.unitType === "person" ? "ADULT" : "OTHER";
40
+ }
41
+ export function deriveOctoAvailabilityStatus(slot, capacityMode) {
42
+ if (slot.status === "sold_out")
43
+ return "SOLD_OUT";
44
+ if (slot.status === "closed" || slot.status === "cancelled")
45
+ return "CLOSED";
46
+ if (capacityMode === "free_sale" || slot.unlimited)
47
+ return "FREESALE";
48
+ if (slot.initialPax !== null &&
49
+ slot.initialPax !== undefined &&
50
+ slot.remainingPax !== null &&
51
+ slot.remainingPax !== undefined) {
52
+ if (slot.remainingPax <= 0)
53
+ return "SOLD_OUT";
54
+ if (slot.initialPax > 0 && slot.remainingPax / slot.initialPax < 0.5)
55
+ return "LIMITED";
56
+ }
57
+ return "AVAILABLE";
58
+ }
59
+ export function mapBookingStatus(status) {
60
+ switch (status) {
61
+ case "on_hold":
62
+ return "ON_HOLD";
63
+ case "expired":
64
+ return "EXPIRED";
65
+ case "cancelled":
66
+ return "CANCELLED";
67
+ default:
68
+ return "CONFIRMED";
69
+ }
70
+ }
71
+ export function mapUnit(unit) {
72
+ return {
73
+ id: unit.id,
74
+ name: unit.name,
75
+ code: unit.code,
76
+ type: inferOctoUnitType(unit),
77
+ restrictions: {
78
+ minAge: unit.minAge ?? undefined,
79
+ maxAge: unit.maxAge ?? undefined,
80
+ minQuantity: unit.minQuantity ?? undefined,
81
+ maxQuantity: unit.maxQuantity ?? undefined,
82
+ occupancyMin: unit.occupancyMin ?? undefined,
83
+ occupancyMax: unit.occupancyMax ?? undefined,
84
+ },
85
+ };
86
+ }
87
+ export function buildProductContent({ features, faqs, locations, }) {
88
+ return {
89
+ highlights: features
90
+ .filter((feature) => feature.featureType === "highlight" || feature.featureType === "other")
91
+ .map((feature) => ({
92
+ id: feature.id,
93
+ title: feature.title,
94
+ description: feature.description,
95
+ })),
96
+ inclusions: features
97
+ .filter((feature) => feature.featureType === "inclusion")
98
+ .map((feature) => ({
99
+ id: feature.id,
100
+ title: feature.title,
101
+ description: feature.description,
102
+ })),
103
+ exclusions: features
104
+ .filter((feature) => feature.featureType === "exclusion")
105
+ .map((feature) => ({
106
+ id: feature.id,
107
+ title: feature.title,
108
+ description: feature.description,
109
+ })),
110
+ importantInformation: features
111
+ .filter((feature) => feature.featureType === "important_information")
112
+ .map((feature) => ({
113
+ id: feature.id,
114
+ title: feature.title,
115
+ description: feature.description,
116
+ })),
117
+ faqs: faqs.map((faq) => ({
118
+ id: faq.id,
119
+ question: faq.question,
120
+ answer: faq.answer,
121
+ })),
122
+ locations: locations.map((location) => ({
123
+ id: location.id,
124
+ type: location.locationType,
125
+ title: location.title,
126
+ address: location.address,
127
+ city: location.city,
128
+ countryCode: location.countryCode,
129
+ latitude: location.latitude,
130
+ longitude: location.longitude,
131
+ googlePlaceId: location.googlePlaceId,
132
+ applePlaceId: location.applePlaceId,
133
+ tripadvisorLocationId: location.tripadvisorLocationId,
134
+ })),
135
+ };
136
+ }
137
+ export function pickOptionStartTimes(option, startTimes) {
138
+ const optionTimes = startTimes.filter((startTime) => startTime.optionId === option.id);
139
+ const sharedTimes = startTimes.filter((startTime) => startTime.optionId === null);
140
+ const source = optionTimes.length > 0 ? optionTimes : sharedTimes;
141
+ return source.map((startTime) => startTime.startTimeLocal);
142
+ }
143
+ export function pickBookingContact(participants) {
144
+ const preferred = participants.find((participant) => participant.participantType === "booker") ??
145
+ participants.find((participant) => participant.participantType === "contact") ??
146
+ participants.find((participant) => participant.isPrimary) ??
147
+ participants[0];
148
+ if (!preferred)
149
+ return null;
150
+ return {
151
+ participantId: preferred.id,
152
+ firstName: preferred.firstName,
153
+ lastName: preferred.lastName,
154
+ email: preferred.email,
155
+ phone: preferred.phone,
156
+ language: preferred.preferredLanguage,
157
+ };
158
+ }
159
+ export function pickPayloadString(payload, keys) {
160
+ if (!payload)
161
+ return null;
162
+ for (const key of keys) {
163
+ const value = payload[key];
164
+ if (typeof value === "string" && value.length > 0) {
165
+ return value;
166
+ }
167
+ }
168
+ return null;
169
+ }
170
+ export function mapBookingArtifact(fulfillment) {
171
+ const payload = fulfillment.payload ?? null;
172
+ const artifactUrl = fulfillment.artifactUrl;
173
+ const downloadUrl = pickPayloadString(payload, ["downloadUrl", "download_url", "url"]) ?? artifactUrl ?? null;
174
+ const pdfUrl = pickPayloadString(payload, ["pdfUrl", "pdf_url"]) ??
175
+ (fulfillment.fulfillmentType === "pdf" ? artifactUrl : null);
176
+ const qrCode = pickPayloadString(payload, ["qrCode", "qr_code"]) ??
177
+ (fulfillment.fulfillmentType === "qr_code"
178
+ ? pickPayloadString(payload, ["code", "voucherCode", "voucher_code"])
179
+ : null);
180
+ const barcode = pickPayloadString(payload, ["barcode", "barcodeValue", "barcode_value"]) ??
181
+ (fulfillment.fulfillmentType === "barcode"
182
+ ? pickPayloadString(payload, ["code", "voucherCode", "voucher_code"])
183
+ : null);
184
+ const voucherCode = pickPayloadString(payload, ["voucherCode", "voucher_code", "code"]);
185
+ return {
186
+ fulfillmentId: fulfillment.id,
187
+ bookingItemId: fulfillment.bookingItemId,
188
+ participantId: fulfillment.participantId,
189
+ type: fulfillment.fulfillmentType,
190
+ deliveryChannel: fulfillment.deliveryChannel,
191
+ status: fulfillment.status,
192
+ artifactUrl,
193
+ downloadUrl,
194
+ pdfUrl,
195
+ qrCode,
196
+ barcode,
197
+ voucherCode,
198
+ issuedAt: toIsoString(fulfillment.issuedAt),
199
+ revokedAt: toIsoString(fulfillment.revokedAt),
200
+ };
201
+ }
202
+ export function buildProjectedAvailability(slot, product) {
203
+ const timeZone = slot.timezone || product?.timezone || "UTC";
204
+ return {
205
+ id: slot.id,
206
+ productId: slot.productId,
207
+ optionId: slot.optionId,
208
+ localDateTimeStart: formatLocalDateTime(slot.startsAt, timeZone),
209
+ localDateTimeEnd: slot.endsAt ? formatLocalDateTime(slot.endsAt, timeZone) : null,
210
+ timeZone,
211
+ status: deriveOctoAvailabilityStatus(slot, product?.capacityMode),
212
+ vacancies: slot.unlimited ? null : slot.remainingPax,
213
+ capacity: slot.unlimited ? null : slot.initialPax,
214
+ };
215
+ }
package/dist/service.d.ts CHANGED
@@ -1,124 +1,21 @@
1
- import { availabilitySlots } from "@voyantjs/availability/schema";
2
- import { bookingsService } from "@voyantjs/bookings";
3
- import { bookingFulfillments, bookings } from "@voyantjs/bookings/schema";
4
- import { optionUnits, products } from "@voyantjs/products/schema";
5
- import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
6
- import type { z } from "zod";
7
- import type { OctoAvailabilityStatus, OctoAvailabilityType, OctoBookingStatus, OctoProjectedAvailability, OctoProjectedBooking, OctoProjectedProduct, OctoUnitType } from "./types.js";
8
- import type { octoAvailabilityCalendarQuerySchema, octoAvailabilityListQuerySchema, octoBookingListQuerySchema, octoProductListQuerySchema } from "./validation.js";
9
- type ProductRow = typeof products.$inferSelect;
10
- type UnitRow = typeof optionUnits.$inferSelect;
11
- type SlotRow = typeof availabilitySlots.$inferSelect;
12
- type BookingRow = typeof bookings.$inferSelect;
13
- type OctoAvailabilityListQuery = z.infer<typeof octoAvailabilityListQuerySchema>;
14
- type OctoAvailabilityCalendarQuery = z.infer<typeof octoAvailabilityCalendarQuerySchema>;
15
- type OctoProductListQuery = z.infer<typeof octoProductListQuerySchema>;
16
- type OctoBookingListQuery = z.infer<typeof octoBookingListQuerySchema>;
17
- export declare function inferOctoAvailabilityType(bookingMode: ProductRow["bookingMode"]): OctoAvailabilityType;
18
- export declare function inferOctoUnitType(unit: Pick<UnitRow, "name" | "code" | "unitType">): OctoUnitType;
19
- export declare function deriveOctoAvailabilityStatus(slot: Pick<SlotRow, "status" | "unlimited" | "initialPax" | "remainingPax">, capacityMode: ProductRow["capacityMode"] | null | undefined): OctoAvailabilityStatus;
20
- export declare function mapBookingStatus(status: BookingRow["status"]): OctoBookingStatus;
21
- export declare function mapBookingArtifact(fulfillment: typeof bookingFulfillments.$inferSelect): {
22
- fulfillmentId: string;
23
- bookingItemId: string | null;
24
- participantId: string | null;
25
- type: "other" | "voucher" | "ticket" | "pdf" | "qr_code" | "barcode" | "mobile";
26
- deliveryChannel: "other" | "download" | "email" | "api" | "wallet";
27
- status: "pending" | "issued" | "reissued" | "revoked" | "failed";
28
- artifactUrl: string | null;
29
- downloadUrl: string | null;
30
- pdfUrl: string | null;
31
- qrCode: string | null;
32
- barcode: string | null;
33
- voucherCode: string | null;
34
- issuedAt: string | null;
35
- revokedAt: string | null;
36
- };
1
+ import { cancelProjectedBooking, confirmProjectedBooking, expireProjectedBooking, extendProjectedBookingHold, getProjectedBookingById, listProjectedBookings, listProjectedRedemptions, recordProjectedRedemption, reserveProjectedBooking } from "./service-bookings.js";
2
+ import { getProjectedAvailabilityById, getProjectedAvailabilityCalendar, getProjectedProductById, listProjectedAvailability, listProjectedProducts } from "./service-products.js";
3
+ import { deriveOctoAvailabilityStatus, inferOctoAvailabilityType, inferOctoUnitType, mapBookingArtifact, mapBookingStatus } from "./service-shared.js";
4
+ export { deriveOctoAvailabilityStatus, inferOctoAvailabilityType, inferOctoUnitType, mapBookingArtifact, mapBookingStatus, };
37
5
  export declare const octoService: {
38
- getProjectedProductById(db: PostgresJsDatabase, id: string): Promise<OctoProjectedProduct | null>;
39
- getProjectedAvailabilityById(db: PostgresJsDatabase, id: string): Promise<OctoProjectedAvailability | null>;
40
- listProjectedAvailability(db: PostgresJsDatabase, query: OctoAvailabilityListQuery): Promise<{
41
- data: OctoProjectedAvailability[];
42
- total: number;
43
- limit: number;
44
- offset: number;
45
- }>;
46
- getProjectedAvailabilityCalendar(db: PostgresJsDatabase, productId: string, query: OctoAvailabilityCalendarQuery): Promise<{
47
- data: {
48
- localDate: string;
49
- status: OctoAvailabilityStatus;
50
- vacancies: number | null;
51
- capacity: number | null;
52
- availabilityIds: string[];
53
- }[];
54
- total: number;
55
- }>;
56
- listProjectedProducts(db: PostgresJsDatabase, query: OctoProductListQuery): Promise<{
57
- data: OctoProjectedProduct[];
58
- total: number;
59
- limit: number;
60
- offset: number;
61
- }>;
62
- getProjectedBookingById(db: PostgresJsDatabase, id: string): Promise<OctoProjectedBooking | null>;
63
- listProjectedBookings(db: PostgresJsDatabase, query: OctoBookingListQuery): Promise<{
64
- data: OctoProjectedBooking[];
65
- total: number;
66
- limit: number;
67
- offset: number;
68
- }>;
69
- reserveProjectedBooking(db: PostgresJsDatabase, data: Parameters<typeof bookingsService.reserveBooking>[1], userId?: string): Promise<{
70
- status: Exclude<string, "ok">;
71
- } | {
72
- status: "ok";
73
- booking: OctoProjectedBooking | null;
74
- }>;
75
- confirmProjectedBooking(db: PostgresJsDatabase, id: string, data: Parameters<typeof bookingsService.confirmBooking>[2], userId?: string): Promise<{
76
- status: Exclude<string, "ok">;
77
- } | {
78
- status: "ok";
79
- booking: OctoProjectedBooking | null;
80
- }>;
81
- extendProjectedBookingHold(db: PostgresJsDatabase, id: string, data: Parameters<typeof bookingsService.extendBookingHold>[2], userId?: string): Promise<{
82
- status: Exclude<string, "ok">;
83
- } | {
84
- status: "ok";
85
- booking: OctoProjectedBooking | null;
86
- }>;
87
- expireProjectedBooking(db: PostgresJsDatabase, id: string, data: Parameters<typeof bookingsService.expireBooking>[2], userId?: string): Promise<{
88
- status: Exclude<string, "ok">;
89
- } | {
90
- status: "ok";
91
- booking: OctoProjectedBooking | null;
92
- }>;
93
- cancelProjectedBooking(db: PostgresJsDatabase, id: string, data: Parameters<typeof bookingsService.cancelBooking>[2], userId?: string): Promise<{
94
- status: Exclude<string, "ok">;
95
- } | {
96
- status: "ok";
97
- booking: OctoProjectedBooking | null;
98
- }>;
99
- listProjectedRedemptions(db: PostgresJsDatabase, bookingId: string): Promise<{
100
- id: string;
101
- bookingItemId: string | null;
102
- participantId: string | null;
103
- redeemedAt: string;
104
- redeemedBy: string | null;
105
- location: string | null;
106
- method: "other" | "manual" | "api" | "scan";
107
- metadata: Record<string, unknown> | null;
108
- }[]>;
109
- recordProjectedRedemption(db: PostgresJsDatabase, bookingId: string, data: Parameters<typeof bookingsService.recordRedemption>[2], userId?: string): Promise<{
110
- event: {
111
- id: string;
112
- bookingItemId: string | null;
113
- participantId: string | null;
114
- redeemedAt: string;
115
- redeemedBy: string | null;
116
- location: string | null;
117
- method: "other" | "manual" | "api" | "scan";
118
- metadata: Record<string, unknown> | null;
119
- };
120
- booking: OctoProjectedBooking | null;
121
- } | null>;
6
+ getProjectedProductById: typeof getProjectedProductById;
7
+ getProjectedAvailabilityById: typeof getProjectedAvailabilityById;
8
+ listProjectedAvailability: typeof listProjectedAvailability;
9
+ getProjectedAvailabilityCalendar: typeof getProjectedAvailabilityCalendar;
10
+ listProjectedProducts: typeof listProjectedProducts;
11
+ getProjectedBookingById: typeof getProjectedBookingById;
12
+ listProjectedBookings: typeof listProjectedBookings;
13
+ reserveProjectedBooking: typeof reserveProjectedBooking;
14
+ confirmProjectedBooking: typeof confirmProjectedBooking;
15
+ extendProjectedBookingHold: typeof extendProjectedBookingHold;
16
+ expireProjectedBooking: typeof expireProjectedBooking;
17
+ cancelProjectedBooking: typeof cancelProjectedBooking;
18
+ listProjectedRedemptions: typeof listProjectedRedemptions;
19
+ recordProjectedRedemption: typeof recordProjectedRedemption;
122
20
  };
123
- export {};
124
21
  //# sourceMappingURL=service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,EAC1B,uBAAuB,EACvB,qBAAqB,EACrB,wBAAwB,EACxB,yBAAyB,EACzB,uBAAuB,EACxB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,4BAA4B,EAC5B,gCAAgC,EAChC,uBAAuB,EACvB,yBAAyB,EACzB,qBAAqB,EACtB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,4BAA4B,EAC5B,yBAAyB,EACzB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,4BAA4B,EAC5B,yBAAyB,EACzB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,GACjB,CAAA;AAED,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;CAevB,CAAA"}