@perdieminc/time-slots 0.0.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,264 @@
1
+ import { differenceInDays } from "date-fns";
2
+ import {
3
+ DEFAULT_TIMEZONE,
4
+ FULFILLMENT_TYPES,
5
+ PLATFORM,
6
+ PREP_TIME_CADENCE,
7
+ } from "../constants";
8
+ import type {
9
+ CartItem,
10
+ FulfillmentSchedule,
11
+ GetSchedulesParams,
12
+ GetSchedulesResult,
13
+ PrepTimeSettings,
14
+ PreSaleConfig,
15
+ } from "../types";
16
+ import { getLocationsBusinessHoursOverrides } from "../utils/business-hours";
17
+ import { getCateringPrepTimeConfig } from "../utils/catering";
18
+ import { getPreSalePickupDates, overrideTimeZoneOnUTC } from "../utils/date";
19
+ import { filterBusyTimesFromSchedule } from "../utils/schedule-filter";
20
+ import { generateLocationFulfillmentSchedule } from "./location";
21
+
22
+ // ── Helpers ─────────────────────────────────────────────────────────────────
23
+
24
+ function deriveCartInfo(cartItems: CartItem[]) {
25
+ return {
26
+ hasPreSaleItem: cartItems.some((item) => item.preSale),
27
+ hasWeeklyPreSaleItem: cartItems.some((item) => item.weeklyPreSale),
28
+ categoryIds: Array.from(
29
+ new Set(
30
+ cartItems
31
+ .map((item) => item.internalCategoryId)
32
+ .filter((id): id is string => Boolean(id)),
33
+ ),
34
+ ),
35
+ };
36
+ }
37
+
38
+ function resolvePreSaleDates(
39
+ preSaleConfig: PreSaleConfig | undefined,
40
+ timezone: string,
41
+ ) {
42
+ return {
43
+ startDate: preSaleConfig?.due_start_date
44
+ ? overrideTimeZoneOnUTC(preSaleConfig.due_start_date, timezone)
45
+ : new Date(),
46
+ endDate: preSaleConfig?.due_end_date
47
+ ? overrideTimeZoneOnUTC(preSaleConfig.due_end_date, timezone)
48
+ : new Date(),
49
+ };
50
+ }
51
+
52
+ function getPreSaleHoursOverride(
53
+ preSaleConfig: PreSaleConfig | undefined,
54
+ hasPreSaleItem: boolean,
55
+ ) {
56
+ if (
57
+ preSaleConfig &&
58
+ !preSaleConfig.use_store_hours_due &&
59
+ hasPreSaleItem &&
60
+ preSaleConfig.due_start_time &&
61
+ preSaleConfig.due_end_time
62
+ ) {
63
+ return [
64
+ {
65
+ startTime: preSaleConfig.due_start_time,
66
+ endTime: preSaleConfig.due_end_time,
67
+ },
68
+ ];
69
+ }
70
+ return null;
71
+ }
72
+
73
+ function resolveStartDate(
74
+ zonedDueStartDate: Date,
75
+ hasPreSaleItem: boolean,
76
+ ): Date {
77
+ if (hasPreSaleItem) {
78
+ return new Date(Math.max(zonedDueStartDate.getTime(), Date.now()));
79
+ }
80
+ return new Date();
81
+ }
82
+ const WEEKDAY_KEYS = [0, 1, 2, 3, 4, 5, 6] as const;
83
+
84
+ function addEstimatedDeliveryToWeekDays(
85
+ weekDayPrepTimes: Record<number, number>,
86
+ estimatedDeliveryMinutes: number,
87
+ ): Record<number, number> {
88
+ const result: Record<number, number> = {};
89
+ for (const day of WEEKDAY_KEYS) {
90
+ result[day] = (weekDayPrepTimes[day] ?? 0) + estimatedDeliveryMinutes;
91
+ }
92
+ return result;
93
+ }
94
+
95
+ /**
96
+ * Resolves prep time config: for catering flow uses cart-derived cadence/frequency;
97
+ * when fulfillment is DELIVERY, adds estimatedDeliveryMinutes to all weekday prep times.
98
+ */
99
+ function resolvePrepTimeConfig(
100
+ prepTimeSettings: PrepTimeSettings,
101
+ cartItems: CartItem[],
102
+ isCateringFlow: boolean,
103
+ fulfillmentPreference: "PICKUP" | "DELIVERY" | "CURBSIDE",
104
+ timezone: string = DEFAULT_TIMEZONE,
105
+ ): PrepTimeSettings {
106
+ let resolved: PrepTimeSettings;
107
+
108
+ if (!isCateringFlow) {
109
+ const isDayCadence =
110
+ prepTimeSettings.prepTimeCadence === PREP_TIME_CADENCE.DAY;
111
+ resolved = {
112
+ ...prepTimeSettings,
113
+ ...(isDayCadence && { weekDayPrepTimes: {} }),
114
+ };
115
+ } else {
116
+ const cateringPrepTimeConfig = getCateringPrepTimeConfig({
117
+ items: cartItems,
118
+ prepTimeCadence: prepTimeSettings.prepTimeCadence,
119
+ prepTimeFrequency: prepTimeSettings.prepTimeFrequency,
120
+ timezone,
121
+ });
122
+ resolved = {
123
+ ...prepTimeSettings,
124
+ ...cateringPrepTimeConfig,
125
+ };
126
+ }
127
+ const { estimatedDeliveryMinutes = 0 } = prepTimeSettings;
128
+ if (
129
+ fulfillmentPreference === FULFILLMENT_TYPES.DELIVERY &&
130
+ estimatedDeliveryMinutes > 0
131
+ ) {
132
+ const baseWeekDays = resolved.weekDayPrepTimes ?? {};
133
+ resolved = {
134
+ ...resolved,
135
+ weekDayPrepTimes: addEstimatedDeliveryToWeekDays(
136
+ baseWeekDays,
137
+ prepTimeSettings.estimatedDeliveryMinutes ?? 0,
138
+ ),
139
+ };
140
+ }
141
+
142
+ return resolved;
143
+ }
144
+
145
+ // ── Main ────────────────────────────────────────────────────────────────────
146
+
147
+ export function getSchedules({
148
+ store,
149
+ locations,
150
+ cartItems,
151
+ fulfillmentPreference,
152
+ prepTimeSettings,
153
+ currentLocation,
154
+ isCateringFlow = false,
155
+ platform = PLATFORM.WEB,
156
+ }: GetSchedulesParams): GetSchedulesResult {
157
+ const {
158
+ isAsapOrders,
159
+ isSameDayOrders,
160
+ max_future_order_days: daysCount = 7,
161
+ weeklyPreSaleConfig,
162
+ preSaleConfig,
163
+ } = store;
164
+
165
+ const cart = deriveCartInfo(cartItems);
166
+ const resolvedPrepTime = resolvePrepTimeConfig(
167
+ prepTimeSettings,
168
+ cartItems,
169
+ isCateringFlow,
170
+ fulfillmentPreference,
171
+ currentLocation?.timezone,
172
+ );
173
+ const {
174
+ gapInMinutes,
175
+ busyTimes: busyTimesByLocationId,
176
+ prepTimeFrequency,
177
+ prepTimeCadence,
178
+ weekDayPrepTimes,
179
+ } = resolvedPrepTime;
180
+
181
+ const busyTimes = busyTimesByLocationId?.[currentLocation.location_id] ?? [];
182
+
183
+ const businessHoursOverrides =
184
+ getLocationsBusinessHoursOverrides(store.businessHoursOverrides, locations)[
185
+ currentLocation.location_id
186
+ ] ?? [];
187
+
188
+ const filterSchedule = (schedule: FulfillmentSchedule) =>
189
+ filterBusyTimesFromSchedule({
190
+ schedule,
191
+ busyTimes,
192
+ cartCategoryIds: cart.categoryIds,
193
+ });
194
+
195
+ // ── Weekly pre-sale path (early return) ─────────────────────────────────
196
+ if (
197
+ cart.hasWeeklyPreSaleItem &&
198
+ weeklyPreSaleConfig?.active &&
199
+ !isCateringFlow
200
+ ) {
201
+ const weeklyPickupDates = getPreSalePickupDates(
202
+ weeklyPreSaleConfig?.pickup_days,
203
+ weeklyPreSaleConfig?.ordering_days,
204
+ );
205
+
206
+ if (weeklyPickupDates.length > 0) {
207
+ const schedule = generateLocationFulfillmentSchedule({
208
+ startDate: weeklyPickupDates[0],
209
+ location: currentLocation,
210
+ fulfillmentPreference,
211
+ businessHoursOverrides,
212
+ gapInMinutes,
213
+ daysCount: 7,
214
+ preSaleDates: weeklyPickupDates.map((d) => d.getDate()),
215
+ presalePickupWeekDays: weeklyPreSaleConfig.pickup_days,
216
+ platform,
217
+ });
218
+
219
+ return {
220
+ schedule: filterSchedule(schedule),
221
+ isWeeklyPreSaleAvailable: true,
222
+ };
223
+ }
224
+ }
225
+
226
+ // ── Main schedule path ──────────────────────────────────────────────────
227
+ const isPreSaleEnabled =
228
+ (preSaleConfig?.active ?? false) && cart.hasPreSaleItem && !isCateringFlow;
229
+ const preSaleDates = resolvePreSaleDates(
230
+ preSaleConfig,
231
+ currentLocation.timezone,
232
+ );
233
+ const preSaleHoursOverride = getPreSaleHoursOverride(
234
+ preSaleConfig,
235
+ cart.hasPreSaleItem,
236
+ );
237
+
238
+ const schedule = generateLocationFulfillmentSchedule({
239
+ startDate: resolveStartDate(preSaleDates.startDate, cart.hasPreSaleItem),
240
+ prepTimeFrequency,
241
+ prepTimeCadence,
242
+ location: currentLocation,
243
+ fulfillmentPreference,
244
+ businessHoursOverrides,
245
+ gapInMinutes,
246
+ daysCount: isPreSaleEnabled
247
+ ? differenceInDays(preSaleDates.endDate, preSaleDates.startDate) + 1
248
+ : !isAsapOrders && !isSameDayOrders
249
+ ? daysCount
250
+ : 1,
251
+ platform,
252
+
253
+ ...(!isPreSaleEnabled && {
254
+ weekDayPrepTimes,
255
+ }),
256
+ ...(preSaleHoursOverride && { preSaleHoursOverride }),
257
+ ...(isPreSaleEnabled && { endDate: preSaleDates.endDate }),
258
+ });
259
+
260
+ return {
261
+ schedule: filterSchedule(schedule),
262
+ isWeeklyPreSaleAvailable: false,
263
+ };
264
+ }
@@ -0,0 +1,58 @@
1
+ import { roundToNearestMinutes } from "date-fns";
2
+ import { PLATFORM, PREP_TIME_CADENCE } from "../constants";
3
+ import type {
4
+ FulfillmentSchedule,
5
+ GenerateLocationFulfillmentScheduleParams,
6
+ } from "../types";
7
+ import { getLocationBusinessHoursForFulfillment } from "../utils/business-hours";
8
+ import { getNextAvailableDates } from "./available-dates";
9
+ import { generateSchedule } from "./generate";
10
+
11
+ export function generateLocationFulfillmentSchedule({
12
+ startDate,
13
+ prepTimeFrequency = 0,
14
+ prepTimeCadence = PREP_TIME_CADENCE.MINUTE,
15
+ weekDayPrepTimes,
16
+ location,
17
+ fulfillmentPreference,
18
+ businessHoursOverrides = [],
19
+ preSaleHoursOverride,
20
+ gapInMinutes,
21
+ daysCount = 1,
22
+ preSaleDates = [],
23
+ presalePickupWeekDays = [],
24
+ endDate = null,
25
+ platform = PLATFORM.WEB,
26
+ }: GenerateLocationFulfillmentScheduleParams): FulfillmentSchedule {
27
+ const isDaysCadence = prepTimeCadence === PREP_TIME_CADENCE.DAY;
28
+ const businessHours = getLocationBusinessHoursForFulfillment(
29
+ location,
30
+ fulfillmentPreference,
31
+ );
32
+
33
+ const dates = getNextAvailableDates({
34
+ startDate,
35
+ businessHours,
36
+ businessHoursOverrides,
37
+ timeZone: location.timezone,
38
+ datesCount: daysCount,
39
+ preSaleDates,
40
+ endDate,
41
+ presalePickupWeekDays,
42
+ isDaysCadence,
43
+ platform,
44
+ });
45
+ // If prepTimeCadence is days, we need to skip opening days by prepTimeFrequency
46
+ const availableDates = isDaysCadence ? dates.slice(prepTimeFrequency) : dates;
47
+ return generateSchedule({
48
+ currentDate: roundToNearestMinutes(startDate),
49
+ weekDayPrepTimes,
50
+ timeZone: location.timezone,
51
+ dates: availableDates,
52
+ businessHours,
53
+ businessHoursOverrides,
54
+ preSaleHoursOverride,
55
+ gapInMinutes,
56
+ prepTimeCadence,
57
+ });
58
+ }
@@ -0,0 +1,32 @@
1
+ /** Raw business-hour record from the API (snake_case keys). */
2
+ export interface BusinessHourInput {
3
+ day: number;
4
+ start_time: string;
5
+ end_time: string;
6
+ }
7
+
8
+ /** Normalised business-hour used internally (camelCase keys). */
9
+ export interface BusinessHour {
10
+ day: number;
11
+ startTime: string;
12
+ endTime: string;
13
+ }
14
+
15
+ /** Raw business-hours override coming from the API. */
16
+ export interface BusinessHoursOverrideInput {
17
+ all_locations?: boolean;
18
+ location_ids?: string[];
19
+ month: number;
20
+ day: number;
21
+ start_time: string | null;
22
+ end_time: string | null;
23
+ is_open?: boolean;
24
+ }
25
+
26
+ /** Normalised business-hours override. */
27
+ export interface BusinessHoursOverrideOutput {
28
+ month: number;
29
+ day: number;
30
+ startTime: string | null;
31
+ endTime: string | null;
32
+ }
@@ -0,0 +1,5 @@
1
+ export interface BusyTimeItem {
2
+ startTime: string;
3
+ endTime: string;
4
+ threshold?: { categoryIds?: string[] };
5
+ }
@@ -0,0 +1,122 @@
1
+ import type { PrepTimeCadence } from "../constants";
2
+
3
+ export interface GetCateringPrepTimeParams {
4
+ items: CartItem[];
5
+ prepTimeCadence?: PrepTimeCadence;
6
+ prepTimeFrequency?: number;
7
+ timezone?: string;
8
+ }
9
+
10
+ import type {
11
+ BusinessHoursOverrideInput,
12
+ BusinessHoursOverrideOutput,
13
+ } from "./business-hours";
14
+ import type { BusyTimeItem } from "./common";
15
+ import type { FulfillmentPreference, LocationLike } from "./location";
16
+ import type { FulfillmentSchedule, Platform } from "./schedule";
17
+
18
+ // ── High-level input objects ────────────────────────────────────────────────
19
+
20
+ export interface PreSaleConfig {
21
+ active: boolean;
22
+ due_start_date?: string | Date;
23
+ due_end_date?: string | Date;
24
+ use_store_hours_due?: boolean;
25
+ due_start_time?: string | null;
26
+ due_end_time?: string | null;
27
+ }
28
+
29
+ export interface WeeklyPreSaleConfig {
30
+ active: boolean;
31
+ pickup_days: number[];
32
+ ordering_days: number[];
33
+ }
34
+
35
+ export interface StoreConfig {
36
+ isAsapOrders: boolean;
37
+ isSameDayOrders: boolean;
38
+ max_future_order_days?: number;
39
+ businessHoursOverrides: BusinessHoursOverrideInput[];
40
+ preSaleConfig?: PreSaleConfig;
41
+ weeklyPreSaleConfig?: WeeklyPreSaleConfig;
42
+ }
43
+ export type CateringServiceType = {
44
+ min_quantity: number;
45
+ max_quantity: number;
46
+ serve_count: number;
47
+ prep_time: {
48
+ cadence: PrepTimeCadence;
49
+ frequency: number;
50
+ };
51
+ };
52
+ export interface CartItem {
53
+ preSale?: boolean;
54
+ weeklyPreSale?: boolean;
55
+ internalCategoryId?: string;
56
+ cateringService?: CateringServiceType;
57
+ }
58
+ export interface CateringPrepTimeResult {
59
+ prepTimeCadence: PrepTimeCadence;
60
+ prepTimeFrequency: number;
61
+ /** Only set when prepTimeCadence is not DAY (e.g. HOUR). */
62
+ weekDayPrepTimes?: Record<number, number>;
63
+ }
64
+
65
+ export interface PrepTimeSettings {
66
+ prepTimeInMinutes: number;
67
+ weekDayPrepTimes: Record<number, number>;
68
+ gapInMinutes: number;
69
+ busyTimes: Record<string, BusyTimeItem[]>;
70
+ prepTimeFrequency: number;
71
+ prepTimeCadence: PrepTimeCadence;
72
+ /** When fulfillment is DELIVERY, added to each weekday prep time so slots reflect when order is received. */
73
+ estimatedDeliveryMinutes?: number;
74
+ }
75
+
76
+ // ── getSchedules params / result ────────────────────────────────────────────
77
+
78
+ export interface GetSchedulesParams {
79
+ store: StoreConfig;
80
+ locations: LocationLike[];
81
+ cartItems: CartItem[];
82
+ fulfillmentPreference: FulfillmentPreference;
83
+ prepTimeSettings: PrepTimeSettings;
84
+ currentLocation: LocationLike;
85
+ isCateringFlow?: boolean;
86
+ /** Platform for timezone handling in next-available-date logic. Default "web". */
87
+ platform?: Platform;
88
+ }
89
+
90
+ export interface GetSchedulesResult {
91
+ schedule: FulfillmentSchedule;
92
+ isWeeklyPreSaleAvailable: boolean;
93
+ }
94
+
95
+ // ── Legacy flat params (kept for backward-compat if needed) ─────────────────
96
+
97
+ export interface InitScheduleParams {
98
+ isAsapOrders: boolean;
99
+ isSameDayOrders: boolean;
100
+ preSalePickupDays: number[];
101
+ isWeeklyPreSaleActive: boolean;
102
+ preSaleOrderingDays: number[];
103
+ locations: LocationLike[];
104
+ daysCount?: number;
105
+ fulfillmentPreference: FulfillmentPreference;
106
+ prepTimeInMinutes: number;
107
+ weekDayPrepTimes: Record<number, number>;
108
+ hasCartWeeklyPreSaleItem: boolean;
109
+ busyTimes: BusyTimeItem[];
110
+ cartCategoryIds: string[];
111
+ gapInMinutes: number;
112
+ businessHoursOverrides: Record<string, BusinessHoursOverrideOutput[]>;
113
+ currentLocation: LocationLike;
114
+ }
115
+
116
+ export interface InitScheduleResult {
117
+ businessHoursOverrides: Record<string, BusinessHoursOverrideOutput[]>;
118
+ locationId: string;
119
+ fulfillmentPreference: FulfillmentPreference;
120
+ schedule: FulfillmentSchedule;
121
+ isWeeklyPreSaleAvailable: boolean;
122
+ }
@@ -0,0 +1,34 @@
1
+ export type {
2
+ BusinessHour,
3
+ BusinessHourInput,
4
+ BusinessHoursOverrideInput,
5
+ BusinessHoursOverrideOutput,
6
+ } from "./business-hours";
7
+ export type { BusyTimeItem } from "./common";
8
+ export type {
9
+ CartItem,
10
+ CateringPrepTimeResult,
11
+ GetCateringPrepTimeParams,
12
+ GetSchedulesParams,
13
+ GetSchedulesResult,
14
+ InitScheduleParams,
15
+ InitScheduleResult,
16
+ PrepTimeSettings,
17
+ PreSaleConfig,
18
+ StoreConfig,
19
+ WeeklyPreSaleConfig,
20
+ } from "./get-schedules";
21
+ export type { FulfillmentPreference, LocationLike } from "./location";
22
+ export type {
23
+ DaySchedule,
24
+ FulfillmentSchedule,
25
+ GenerateLocationFulfillmentScheduleParams,
26
+ GenerateScheduleParams,
27
+ GetNextAvailableDatesParams,
28
+ GetOpeningClosingTimeOnDateParams,
29
+ Platform,
30
+ } from "./schedule";
31
+ export type {
32
+ FilterBusyTimesFromScheduleParams,
33
+ MenuType,
34
+ } from "./schedule-filter";
@@ -0,0 +1,25 @@
1
+ import type { BusinessHourInput } from "./business-hours";
2
+
3
+ export type FulfillmentPreference = "PICKUP" | "DELIVERY" | "CURBSIDE";
4
+ export type BusinessHourType = {
5
+ day: number;
6
+ start_time: string;
7
+ end_time: string;
8
+ };
9
+ export interface LocationLike {
10
+ location_id: string;
11
+ id?: string;
12
+ timezone: string;
13
+ pickup_hours?: BusinessHourInput[];
14
+ delivery_hours?: BusinessHourInput[];
15
+ curbside_hours?: {
16
+ use_pickup_hours?: boolean;
17
+ times?: BusinessHourInput[];
18
+ };
19
+ catering?: {
20
+ enabled: boolean | string;
21
+ pickup: Omit<BusinessHourType, "day">;
22
+ delivery: Omit<BusinessHourType, "day">;
23
+ };
24
+ [key: string]: unknown;
25
+ }
@@ -0,0 +1,27 @@
1
+ import type { BusyTimeItem } from "./common";
2
+ import type { FulfillmentSchedule } from "./schedule";
3
+ export type MenuTimeSlot = {
4
+ all_day: boolean;
5
+ end_time: string | null;
6
+ start_time: string | null;
7
+ };
8
+
9
+ export type MenuType = {
10
+ menu_id: string;
11
+ store_id: string;
12
+ location_id: string | null;
13
+ all_locations: boolean;
14
+ display_name: string;
15
+ description: string | null;
16
+ times: Record<string, MenuTimeSlot>;
17
+ category_ids: string[];
18
+ last_modified_by: string;
19
+ created_at: string;
20
+ updated_at: string;
21
+ };
22
+
23
+ export interface FilterBusyTimesFromScheduleParams {
24
+ schedule: FulfillmentSchedule;
25
+ busyTimes?: BusyTimeItem[];
26
+ cartCategoryIds?: string[];
27
+ }
@@ -0,0 +1,83 @@
1
+ import type { PLATFORM } from "../constants";
2
+ import type {
3
+ BusinessHour,
4
+ BusinessHoursOverrideOutput,
5
+ } from "./business-hours";
6
+ import type { FulfillmentPreference, LocationLike } from "./location";
7
+
8
+ export interface DaySchedule {
9
+ date: Date;
10
+ originalStoreOpeningTime: Date | null;
11
+ originalStoreClosingTime: Date | null;
12
+ remainingShifts: number;
13
+ openingTime: Date;
14
+ closingTime: Date;
15
+ firstAvailableSlot: Date;
16
+ slots: Date[];
17
+ [key: string]: unknown;
18
+ }
19
+
20
+ export type FulfillmentSchedule = DaySchedule[];
21
+
22
+ export interface GenerateScheduleParams {
23
+ currentDate?: Date;
24
+ prepTimeBehaviour?: number;
25
+ prepTimeInMinutes?: number;
26
+ weekDayPrepTimes?: Record<number, number>;
27
+ timeZone: string;
28
+ dates?: Date[];
29
+ businessHours?: BusinessHour[];
30
+ businessHoursOverrides?: BusinessHoursOverrideOutput[];
31
+ preSaleHoursOverride?: Array<{
32
+ startTime: string;
33
+ endTime: string;
34
+ month?: number;
35
+ day?: number;
36
+ }> | null;
37
+ gapInMinutes?: number;
38
+ prepTimeCadence?: PrepTimeCadence;
39
+ }
40
+ export type Platform = (typeof PLATFORM)[keyof typeof PLATFORM];
41
+ export interface GetNextAvailableDatesParams {
42
+ startDate: Date;
43
+ timeZone: string;
44
+ businessHours: BusinessHour[];
45
+ businessHoursOverrides?: BusinessHoursOverrideOutput[];
46
+ datesCount?: number;
47
+ preSaleDates?: number[];
48
+ presalePickupWeekDays?: number[];
49
+ endDate?: Date | null;
50
+ isDaysCadence?: boolean;
51
+ /** Platform for timezone handling. Web uses @date-fns/tz; ios/android use timezone-support. Default "web". */
52
+ platform?: Platform;
53
+ }
54
+
55
+ export interface GenerateLocationFulfillmentScheduleParams {
56
+ startDate: Date;
57
+ prepTimeFrequency?: number;
58
+ prepTimeCadence?: PrepTimeCadence;
59
+ weekDayPrepTimes?: Record<number, number>;
60
+ location: LocationLike;
61
+ fulfillmentPreference: FulfillmentPreference;
62
+ /** Overrides for this location only (not keyed by location_id). */
63
+ businessHoursOverrides?: BusinessHoursOverrideOutput[];
64
+ preSaleHoursOverride?: Array<{
65
+ startTime: string;
66
+ endTime: string;
67
+ month?: number;
68
+ day?: number;
69
+ }> | null;
70
+ gapInMinutes?: number;
71
+ daysCount?: number;
72
+ preSaleDates?: number[];
73
+ presalePickupWeekDays?: number[];
74
+ endDate?: Date | null;
75
+ platform?: Platform;
76
+ }
77
+
78
+ export interface GetOpeningClosingTimeOnDateParams {
79
+ date?: Date;
80
+ businessHours?: BusinessHour[];
81
+ businessHoursOverrides?: BusinessHoursOverrideOutput[];
82
+ timeZone: string;
83
+ }
@@ -0,0 +1,31 @@
1
+ declare module "timezone-support" {
2
+ export function findTimeZone(timezone: string): string;
3
+ export function getUnixTime(time: {
4
+ zone: string;
5
+ year: number;
6
+ month: number;
7
+ day: number;
8
+ hours: number | string;
9
+ minutes: number | string;
10
+ seconds: number | string;
11
+ milliseconds: number | string;
12
+ }): number;
13
+ export function getZonedTime(
14
+ date: Date | number,
15
+ timezone: string,
16
+ ): {
17
+ zone: string;
18
+ year: number;
19
+ month: number;
20
+ day: number;
21
+ hours: number | string;
22
+ minutes: number | string;
23
+ seconds: number | string;
24
+ milliseconds: number | string;
25
+ dayOfWeek: number;
26
+ };
27
+ export function toZonedTime(
28
+ date: Date | number | string,
29
+ timezone: string,
30
+ ): Date;
31
+ }