order3000 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.cjs CHANGED
@@ -215,6 +215,20 @@ class EventsResource extends BaseResource {
215
215
  async get(eventId) {
216
216
  return this.request("GET", `/${eventId}`);
217
217
  }
218
+ /**
219
+ * Get an event by accessor (slug)
220
+ * @param accessor - The event accessor (e.g., 'lunch-menu')
221
+ * @param options - Optional expand options
222
+ * @returns The event with optional schedule, timeSlots, menus, and posters
223
+ */
224
+ async getByAccessor(accessor, options) {
225
+ const queryString = this.buildQueryString(options);
226
+ return this.request("GET", `/${accessor}${queryString}`);
227
+ }
228
+ buildQueryString(options) {
229
+ if (!options?.expand?.length) return "";
230
+ return `?expand=${options.expand.join(",")}`;
231
+ }
218
232
  }
219
233
 
220
234
  class MenusResource extends BaseResource {
@@ -486,6 +500,120 @@ class RealtimeManager {
486
500
  }
487
501
  }
488
502
 
503
+ const ALL_DAYS = [
504
+ "monday",
505
+ "tuesday",
506
+ "wednesday",
507
+ "thursday",
508
+ "friday",
509
+ "saturday",
510
+ "sunday"
511
+ ];
512
+ const RRULE_DAY_MAP = {
513
+ MO: "monday",
514
+ TU: "tuesday",
515
+ WE: "wednesday",
516
+ TH: "thursday",
517
+ FR: "friday",
518
+ SA: "saturday",
519
+ SU: "sunday"
520
+ };
521
+ function parseDaysFromRRule(rrule) {
522
+ if (!rrule) {
523
+ return [];
524
+ }
525
+ const byDayMatch = rrule.match(/BYDAY=([^;]+)/);
526
+ if (!byDayMatch) {
527
+ return [];
528
+ }
529
+ const rruleDays = byDayMatch[1].split(",");
530
+ const days = [];
531
+ for (const rruleDay of rruleDays) {
532
+ const day = RRULE_DAY_MAP[rruleDay.trim()];
533
+ if (day) {
534
+ days.push(day);
535
+ }
536
+ }
537
+ return ALL_DAYS.filter((day) => days.includes(day));
538
+ }
539
+ function addMinutesToTime(time, minutes) {
540
+ const parts = time.split(":");
541
+ const hours = parseInt(parts[0], 10);
542
+ const mins = parseInt(parts[1], 10);
543
+ const totalMinutes = hours * 60 + mins + minutes;
544
+ const newHours = Math.floor(totalMinutes / 60) % 24;
545
+ const newMins = totalMinutes % 60;
546
+ return `${newHours.toString().padStart(2, "0")}:${newMins.toString().padStart(2, "0")}`;
547
+ }
548
+ function formatTime(time) {
549
+ const parts = time.split(":");
550
+ if (parts.length >= 2) {
551
+ return `${parts[0]}:${parts[1]}`;
552
+ }
553
+ return time;
554
+ }
555
+ function getScheduleInfo(schedule) {
556
+ const defaultData = {
557
+ timeRange: null,
558
+ activeDays: []
559
+ };
560
+ if (!schedule?.scheduleTimeSlots?.length) {
561
+ return defaultData;
562
+ }
563
+ const timeSlots = schedule.scheduleTimeSlots;
564
+ const rrule = schedule.rrule;
565
+ const intervalMinutes = schedule.intervalMinutes ?? 30;
566
+ const activeDaysSet = /* @__PURE__ */ new Set();
567
+ let hasNullDayOfWeek = false;
568
+ const startTimes = [];
569
+ let latestEndTime = null;
570
+ for (const slot of timeSlots) {
571
+ if (slot.dayOfWeek) {
572
+ activeDaysSet.add(slot.dayOfWeek);
573
+ } else {
574
+ hasNullDayOfWeek = true;
575
+ }
576
+ if (slot.timeSlot.startTime) {
577
+ startTimes.push(slot.timeSlot.startTime);
578
+ }
579
+ if (slot.timeSlot.endTime) {
580
+ if (!latestEndTime || slot.timeSlot.endTime > latestEndTime) {
581
+ latestEndTime = slot.timeSlot.endTime;
582
+ }
583
+ }
584
+ }
585
+ let activeDays;
586
+ if (hasNullDayOfWeek) {
587
+ const rruleDays = parseDaysFromRRule(rrule);
588
+ if (rruleDays.length > 0) {
589
+ activeDays = rruleDays;
590
+ } else {
591
+ activeDays = ALL_DAYS.filter((day) => activeDaysSet.has(day));
592
+ }
593
+ } else {
594
+ activeDays = ALL_DAYS.filter((day) => activeDaysSet.has(day));
595
+ }
596
+ let timeRange = null;
597
+ if (startTimes.length > 0) {
598
+ startTimes.sort();
599
+ const earliestStart = startTimes[0];
600
+ const latestStart = startTimes[startTimes.length - 1];
601
+ let endTime;
602
+ if (latestEndTime) {
603
+ endTime = latestEndTime;
604
+ } else {
605
+ endTime = addMinutesToTime(latestStart, intervalMinutes);
606
+ }
607
+ const startFormatted = formatTime(earliestStart);
608
+ const endFormatted = formatTime(endTime);
609
+ timeRange = `${startFormatted}-${endFormatted}`;
610
+ }
611
+ return {
612
+ timeRange,
613
+ activeDays
614
+ };
615
+ }
616
+
489
617
  var __defProp = Object.defineProperty;
490
618
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
491
619
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -520,3 +648,4 @@ class Order3000Client {
520
648
  }
521
649
 
522
650
  exports.Order3000Client = Order3000Client;
651
+ exports.getScheduleInfo = getScheduleInfo;
package/dist/client.d.cts CHANGED
@@ -27,6 +27,79 @@ declare abstract class BaseResource {
27
27
 
28
28
  interface components {
29
29
  schemas: {
30
+ /**
31
+ * CreateEventRequest
32
+ * @description Request payload for creating a new event
33
+ */
34
+ CreateEventRequest: {
35
+ accessor?: string | null;
36
+ name: (string | number | boolean | (null)) | {
37
+ [key: string]: unknown;
38
+ } | unknown[];
39
+ description?: ((string | number | boolean | (null)) | {
40
+ [key: string]: unknown;
41
+ } | unknown[]) | null;
42
+ scheduleId?: string | null;
43
+ maxBookings?: number | null;
44
+ maxGuests?: number | null;
45
+ minPartySize?: number | null;
46
+ maxPartySize?: number | null;
47
+ isPublic?: boolean;
48
+ isRecurring?: boolean;
49
+ acceptsReservations?: boolean;
50
+ bookingOpensAtDays?: number | null;
51
+ bookingClosesAtHours?: number | null;
52
+ isActive?: boolean;
53
+ isFeatured?: boolean;
54
+ priority?: number;
55
+ schedule?: {
56
+ rrule?: string | null;
57
+ timezone?: string | null;
58
+ validFrom?: string | null;
59
+ validTo?: string | null;
60
+ timeRanges: {
61
+ startTime: string;
62
+ endTime: string;
63
+ lastSeatingTime?: string | null;
64
+ }[];
65
+ /** @enum {string|null} */
66
+ slotMode?: "interval" | "duration" | null;
67
+ intervalMinutes?: number | null;
68
+ durationMinutes?: number | null;
69
+ } | null;
70
+ };
71
+ /**
72
+ * CreateEventResponse
73
+ * @description Successfully created event
74
+ */
75
+ CreateEventResponse: {
76
+ id: string;
77
+ venueId: string;
78
+ accessor: string | null;
79
+ name: (string | number | boolean | (null)) | {
80
+ [key: string]: unknown;
81
+ } | unknown[];
82
+ description: ((string | number | boolean | (null)) | {
83
+ [key: string]: unknown;
84
+ } | unknown[]) | null;
85
+ scheduleId: string | null;
86
+ maxBookings: number | null;
87
+ maxGuests: number | null;
88
+ minPartySize: number | null;
89
+ maxPartySize: number | null;
90
+ isPublic: boolean;
91
+ isRecurring: boolean;
92
+ acceptsReservations: boolean;
93
+ bookingOpensAtDays: number | null;
94
+ bookingClosesAtHours: number | null;
95
+ isActive: boolean;
96
+ isFeatured: boolean;
97
+ priority: number;
98
+ createdBy: string | null;
99
+ updatedBy: string | null;
100
+ createdAt: unknown;
101
+ updatedAt: unknown;
102
+ };
30
103
  /**
31
104
  * PlaceOrderRequest
32
105
  * @description Place a new order for a specific venue
@@ -205,79 +278,6 @@ interface components {
205
278
  /** @description Last update timestamp */
206
279
  updatedAt: unknown;
207
280
  };
208
- /**
209
- * CreateEventRequest
210
- * @description Request payload for creating a new event
211
- */
212
- CreateEventRequest: {
213
- accessor?: string | null;
214
- name: (string | number | boolean | (null)) | {
215
- [key: string]: unknown;
216
- } | unknown[];
217
- description?: ((string | number | boolean | (null)) | {
218
- [key: string]: unknown;
219
- } | unknown[]) | null;
220
- scheduleId?: string | null;
221
- maxBookings?: number | null;
222
- maxGuests?: number | null;
223
- minPartySize?: number | null;
224
- maxPartySize?: number | null;
225
- isPublic?: boolean;
226
- isRecurring?: boolean;
227
- acceptsReservations?: boolean;
228
- bookingOpensAtDays?: number | null;
229
- bookingClosesAtHours?: number | null;
230
- isActive?: boolean;
231
- isFeatured?: boolean;
232
- priority?: number;
233
- schedule?: {
234
- rrule?: string | null;
235
- timezone?: string | null;
236
- validFrom?: string | null;
237
- validTo?: string | null;
238
- timeRanges: {
239
- startTime: string;
240
- endTime: string;
241
- lastSeatingTime?: string | null;
242
- }[];
243
- /** @enum {string|null} */
244
- slotMode?: "interval" | "duration" | null;
245
- intervalMinutes?: number | null;
246
- durationMinutes?: number | null;
247
- } | null;
248
- };
249
- /**
250
- * CreateEventResponse
251
- * @description Successfully created event
252
- */
253
- CreateEventResponse: {
254
- id: string;
255
- venueId: string;
256
- accessor: string | null;
257
- name: (string | number | boolean | (null)) | {
258
- [key: string]: unknown;
259
- } | unknown[];
260
- description: ((string | number | boolean | (null)) | {
261
- [key: string]: unknown;
262
- } | unknown[]) | null;
263
- scheduleId: string | null;
264
- maxBookings: number | null;
265
- maxGuests: number | null;
266
- minPartySize: number | null;
267
- maxPartySize: number | null;
268
- isPublic: boolean;
269
- isRecurring: boolean;
270
- acceptsReservations: boolean;
271
- bookingOpensAtDays: number | null;
272
- bookingClosesAtHours: number | null;
273
- isActive: boolean;
274
- isFeatured: boolean;
275
- priority: number;
276
- createdBy: string | null;
277
- updatedBy: string | null;
278
- createdAt: unknown;
279
- updatedAt: unknown;
280
- };
281
281
  };
282
282
  responses: never;
283
283
  parameters: never;
@@ -293,11 +293,12 @@ type PlaceOrderRequest = schemas['PlaceOrderRequest'];
293
293
  type PlaceOrderResponse = schemas['PlaceOrderResponse'];
294
294
  type MakeReservationRequest = schemas['MakeReservationRequest'];
295
295
  type MakeReservationResponse = schemas['MakeReservationResponse'];
296
+ type DayOfWeek = 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday';
296
297
  interface TimeSlot {
297
298
  id: string;
298
299
  startTime: string;
299
300
  endTime: string | null;
300
- dayOfWeek?: 'MON' | 'TUE' | 'WED' | 'THU' | 'FRI' | 'SAT' | 'SUN' | null;
301
+ dayOfWeek?: DayOfWeek | null;
301
302
  isSchedulable: boolean | null;
302
303
  }
303
304
  interface ScheduleOverride {
@@ -476,6 +477,54 @@ interface GetMenuOptions {
476
477
  /** Expand related resources (items, assets) */
477
478
  expand?: ('items' | 'assets')[];
478
479
  }
480
+ interface ScheduleTimeSlot {
481
+ dayOfWeek: DayOfWeek | null;
482
+ timeSlot: {
483
+ id: string;
484
+ startTime: string;
485
+ endTime: string | null;
486
+ isActive: boolean | null;
487
+ isSchedulable: boolean | null;
488
+ };
489
+ }
490
+ interface ScheduleWithTimeSlots extends Schedule {
491
+ scheduleTimeSlots?: ScheduleTimeSlot[];
492
+ }
493
+ interface EventMenu {
494
+ id: string;
495
+ accessor: string;
496
+ name: Record<string, string>;
497
+ category: string;
498
+ }
499
+ interface EventByAccessor {
500
+ id: string;
501
+ venueId: string;
502
+ accessor: string | null;
503
+ name: Record<string, string>;
504
+ description: Record<string, string> | null;
505
+ scheduleId: string | null;
506
+ maxBookings: number | null;
507
+ maxGuests: number | null;
508
+ minPartySize: number | null;
509
+ maxPartySize: number | null;
510
+ isPublic: boolean;
511
+ isRecurring: boolean;
512
+ acceptsReservations: boolean;
513
+ bookingOpensAtDays: number | null;
514
+ bookingClosesAtHours: number | null;
515
+ isActive: boolean;
516
+ isFeatured: boolean;
517
+ priority: number;
518
+ createdAt: string | null;
519
+ updatedAt: string | null;
520
+ schedule?: ScheduleWithTimeSlots;
521
+ menus?: EventMenu[];
522
+ posters?: EventPoster[];
523
+ }
524
+ interface GetEventOptions {
525
+ /** Expand related resources (schedule, timeSlots, menus, posters) */
526
+ expand?: ('schedule' | 'timeSlots' | 'menus' | 'posters')[];
527
+ }
479
528
  type BasketStatus = 'active' | 'abandoned' | 'converted';
480
529
  type Currency = 'EUR' | 'CHF';
481
530
  /**
@@ -601,6 +650,14 @@ declare class EventsResource extends BaseResource {
601
650
  * @returns The event details
602
651
  */
603
652
  get(eventId: string): Promise<Event>;
653
+ /**
654
+ * Get an event by accessor (slug)
655
+ * @param accessor - The event accessor (e.g., 'lunch-menu')
656
+ * @param options - Optional expand options
657
+ * @returns The event with optional schedule, timeSlots, menus, and posters
658
+ */
659
+ getByAccessor(accessor: string, options?: GetEventOptions): Promise<EventByAccessor>;
660
+ private buildQueryString;
604
661
  }
605
662
 
606
663
  declare class MenusResource extends BaseResource {
@@ -765,6 +822,26 @@ declare class RealtimeManager {
765
822
  disconnectAll(): Promise<void>;
766
823
  }
767
824
 
825
+ interface ScheduleInfo {
826
+ /** Time range string, e.g. "11:30-15:00" */
827
+ timeRange: string | null;
828
+ /** Active days in week order */
829
+ activeDays: DayOfWeek[];
830
+ }
831
+ interface ScheduleInput {
832
+ rrule?: string | null;
833
+ intervalMinutes?: number | null;
834
+ scheduleTimeSlots?: ScheduleTimeSlot[];
835
+ }
836
+ /**
837
+ * Extract schedule information from a schedule object.
838
+ * Returns time range and active days for display purposes.
839
+ *
840
+ * @param schedule - Schedule object with rrule, intervalMinutes, and scheduleTimeSlots
841
+ * @returns ScheduleInfo with timeRange and activeDays
842
+ */
843
+ declare function getScheduleInfo(schedule: ScheduleInput | null | undefined): ScheduleInfo;
844
+
768
845
  interface Order3000ClientConfig {
769
846
  clientId: string;
770
847
  clientSecret: string;
@@ -792,4 +869,4 @@ declare class Order3000Client {
792
869
  constructor(config: Order3000ClientConfig);
793
870
  }
794
871
 
795
- export { type AddToBasketRequest, type AddToBasketResponse, type Basket, type BasketItem, type BasketItemMenuItemRef, type BasketItemMetadata, type BasketStatus, type CropArea, type Currency, type Event, type EventPoster, type EventRow, type GetMenuOptions, type ListEventsOptions, type ListEventsResponse, type Menu, type MenuAsset, type MenuBeverage, type MenuDish, type MenuItem, type MenuItemRow, type MenuItemType, Order3000Client, type Order3000ClientConfig, type Promotion, type RealtimeConfig, type RealtimeEvent, type RealtimeSubscription, type RemoveFromBasketResponse, type Schedule, type ScheduleOverride, type ScheduleOverrideRow, type ScheduleRow, type SubscriptionOptions, type TimeSlot, type Unit };
872
+ export { type AddToBasketRequest, type AddToBasketResponse, type Basket, type BasketItem, type BasketItemMenuItemRef, type BasketItemMetadata, type BasketStatus, type CropArea, type Currency, type DayOfWeek, type Event, type EventByAccessor, type EventMenu, type EventPoster, type EventRow, type GetEventOptions, type GetMenuOptions, type ListEventsOptions, type ListEventsResponse, type Menu, type MenuAsset, type MenuBeverage, type MenuDish, type MenuItem, type MenuItemRow, type MenuItemType, Order3000Client, type Order3000ClientConfig, type Promotion, type RealtimeConfig, type RealtimeEvent, type RealtimeSubscription, type RemoveFromBasketResponse, type Schedule, type ScheduleInfo, type ScheduleOverride, type ScheduleOverrideRow, type ScheduleRow, type ScheduleTimeSlot, type ScheduleWithTimeSlots, type SubscriptionOptions, type TimeSlot, type Unit, getScheduleInfo };
package/dist/client.d.mts CHANGED
@@ -27,6 +27,79 @@ declare abstract class BaseResource {
27
27
 
28
28
  interface components {
29
29
  schemas: {
30
+ /**
31
+ * CreateEventRequest
32
+ * @description Request payload for creating a new event
33
+ */
34
+ CreateEventRequest: {
35
+ accessor?: string | null;
36
+ name: (string | number | boolean | (null)) | {
37
+ [key: string]: unknown;
38
+ } | unknown[];
39
+ description?: ((string | number | boolean | (null)) | {
40
+ [key: string]: unknown;
41
+ } | unknown[]) | null;
42
+ scheduleId?: string | null;
43
+ maxBookings?: number | null;
44
+ maxGuests?: number | null;
45
+ minPartySize?: number | null;
46
+ maxPartySize?: number | null;
47
+ isPublic?: boolean;
48
+ isRecurring?: boolean;
49
+ acceptsReservations?: boolean;
50
+ bookingOpensAtDays?: number | null;
51
+ bookingClosesAtHours?: number | null;
52
+ isActive?: boolean;
53
+ isFeatured?: boolean;
54
+ priority?: number;
55
+ schedule?: {
56
+ rrule?: string | null;
57
+ timezone?: string | null;
58
+ validFrom?: string | null;
59
+ validTo?: string | null;
60
+ timeRanges: {
61
+ startTime: string;
62
+ endTime: string;
63
+ lastSeatingTime?: string | null;
64
+ }[];
65
+ /** @enum {string|null} */
66
+ slotMode?: "interval" | "duration" | null;
67
+ intervalMinutes?: number | null;
68
+ durationMinutes?: number | null;
69
+ } | null;
70
+ };
71
+ /**
72
+ * CreateEventResponse
73
+ * @description Successfully created event
74
+ */
75
+ CreateEventResponse: {
76
+ id: string;
77
+ venueId: string;
78
+ accessor: string | null;
79
+ name: (string | number | boolean | (null)) | {
80
+ [key: string]: unknown;
81
+ } | unknown[];
82
+ description: ((string | number | boolean | (null)) | {
83
+ [key: string]: unknown;
84
+ } | unknown[]) | null;
85
+ scheduleId: string | null;
86
+ maxBookings: number | null;
87
+ maxGuests: number | null;
88
+ minPartySize: number | null;
89
+ maxPartySize: number | null;
90
+ isPublic: boolean;
91
+ isRecurring: boolean;
92
+ acceptsReservations: boolean;
93
+ bookingOpensAtDays: number | null;
94
+ bookingClosesAtHours: number | null;
95
+ isActive: boolean;
96
+ isFeatured: boolean;
97
+ priority: number;
98
+ createdBy: string | null;
99
+ updatedBy: string | null;
100
+ createdAt: unknown;
101
+ updatedAt: unknown;
102
+ };
30
103
  /**
31
104
  * PlaceOrderRequest
32
105
  * @description Place a new order for a specific venue
@@ -205,79 +278,6 @@ interface components {
205
278
  /** @description Last update timestamp */
206
279
  updatedAt: unknown;
207
280
  };
208
- /**
209
- * CreateEventRequest
210
- * @description Request payload for creating a new event
211
- */
212
- CreateEventRequest: {
213
- accessor?: string | null;
214
- name: (string | number | boolean | (null)) | {
215
- [key: string]: unknown;
216
- } | unknown[];
217
- description?: ((string | number | boolean | (null)) | {
218
- [key: string]: unknown;
219
- } | unknown[]) | null;
220
- scheduleId?: string | null;
221
- maxBookings?: number | null;
222
- maxGuests?: number | null;
223
- minPartySize?: number | null;
224
- maxPartySize?: number | null;
225
- isPublic?: boolean;
226
- isRecurring?: boolean;
227
- acceptsReservations?: boolean;
228
- bookingOpensAtDays?: number | null;
229
- bookingClosesAtHours?: number | null;
230
- isActive?: boolean;
231
- isFeatured?: boolean;
232
- priority?: number;
233
- schedule?: {
234
- rrule?: string | null;
235
- timezone?: string | null;
236
- validFrom?: string | null;
237
- validTo?: string | null;
238
- timeRanges: {
239
- startTime: string;
240
- endTime: string;
241
- lastSeatingTime?: string | null;
242
- }[];
243
- /** @enum {string|null} */
244
- slotMode?: "interval" | "duration" | null;
245
- intervalMinutes?: number | null;
246
- durationMinutes?: number | null;
247
- } | null;
248
- };
249
- /**
250
- * CreateEventResponse
251
- * @description Successfully created event
252
- */
253
- CreateEventResponse: {
254
- id: string;
255
- venueId: string;
256
- accessor: string | null;
257
- name: (string | number | boolean | (null)) | {
258
- [key: string]: unknown;
259
- } | unknown[];
260
- description: ((string | number | boolean | (null)) | {
261
- [key: string]: unknown;
262
- } | unknown[]) | null;
263
- scheduleId: string | null;
264
- maxBookings: number | null;
265
- maxGuests: number | null;
266
- minPartySize: number | null;
267
- maxPartySize: number | null;
268
- isPublic: boolean;
269
- isRecurring: boolean;
270
- acceptsReservations: boolean;
271
- bookingOpensAtDays: number | null;
272
- bookingClosesAtHours: number | null;
273
- isActive: boolean;
274
- isFeatured: boolean;
275
- priority: number;
276
- createdBy: string | null;
277
- updatedBy: string | null;
278
- createdAt: unknown;
279
- updatedAt: unknown;
280
- };
281
281
  };
282
282
  responses: never;
283
283
  parameters: never;
@@ -293,11 +293,12 @@ type PlaceOrderRequest = schemas['PlaceOrderRequest'];
293
293
  type PlaceOrderResponse = schemas['PlaceOrderResponse'];
294
294
  type MakeReservationRequest = schemas['MakeReservationRequest'];
295
295
  type MakeReservationResponse = schemas['MakeReservationResponse'];
296
+ type DayOfWeek = 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday';
296
297
  interface TimeSlot {
297
298
  id: string;
298
299
  startTime: string;
299
300
  endTime: string | null;
300
- dayOfWeek?: 'MON' | 'TUE' | 'WED' | 'THU' | 'FRI' | 'SAT' | 'SUN' | null;
301
+ dayOfWeek?: DayOfWeek | null;
301
302
  isSchedulable: boolean | null;
302
303
  }
303
304
  interface ScheduleOverride {
@@ -476,6 +477,54 @@ interface GetMenuOptions {
476
477
  /** Expand related resources (items, assets) */
477
478
  expand?: ('items' | 'assets')[];
478
479
  }
480
+ interface ScheduleTimeSlot {
481
+ dayOfWeek: DayOfWeek | null;
482
+ timeSlot: {
483
+ id: string;
484
+ startTime: string;
485
+ endTime: string | null;
486
+ isActive: boolean | null;
487
+ isSchedulable: boolean | null;
488
+ };
489
+ }
490
+ interface ScheduleWithTimeSlots extends Schedule {
491
+ scheduleTimeSlots?: ScheduleTimeSlot[];
492
+ }
493
+ interface EventMenu {
494
+ id: string;
495
+ accessor: string;
496
+ name: Record<string, string>;
497
+ category: string;
498
+ }
499
+ interface EventByAccessor {
500
+ id: string;
501
+ venueId: string;
502
+ accessor: string | null;
503
+ name: Record<string, string>;
504
+ description: Record<string, string> | null;
505
+ scheduleId: string | null;
506
+ maxBookings: number | null;
507
+ maxGuests: number | null;
508
+ minPartySize: number | null;
509
+ maxPartySize: number | null;
510
+ isPublic: boolean;
511
+ isRecurring: boolean;
512
+ acceptsReservations: boolean;
513
+ bookingOpensAtDays: number | null;
514
+ bookingClosesAtHours: number | null;
515
+ isActive: boolean;
516
+ isFeatured: boolean;
517
+ priority: number;
518
+ createdAt: string | null;
519
+ updatedAt: string | null;
520
+ schedule?: ScheduleWithTimeSlots;
521
+ menus?: EventMenu[];
522
+ posters?: EventPoster[];
523
+ }
524
+ interface GetEventOptions {
525
+ /** Expand related resources (schedule, timeSlots, menus, posters) */
526
+ expand?: ('schedule' | 'timeSlots' | 'menus' | 'posters')[];
527
+ }
479
528
  type BasketStatus = 'active' | 'abandoned' | 'converted';
480
529
  type Currency = 'EUR' | 'CHF';
481
530
  /**
@@ -601,6 +650,14 @@ declare class EventsResource extends BaseResource {
601
650
  * @returns The event details
602
651
  */
603
652
  get(eventId: string): Promise<Event>;
653
+ /**
654
+ * Get an event by accessor (slug)
655
+ * @param accessor - The event accessor (e.g., 'lunch-menu')
656
+ * @param options - Optional expand options
657
+ * @returns The event with optional schedule, timeSlots, menus, and posters
658
+ */
659
+ getByAccessor(accessor: string, options?: GetEventOptions): Promise<EventByAccessor>;
660
+ private buildQueryString;
604
661
  }
605
662
 
606
663
  declare class MenusResource extends BaseResource {
@@ -765,6 +822,26 @@ declare class RealtimeManager {
765
822
  disconnectAll(): Promise<void>;
766
823
  }
767
824
 
825
+ interface ScheduleInfo {
826
+ /** Time range string, e.g. "11:30-15:00" */
827
+ timeRange: string | null;
828
+ /** Active days in week order */
829
+ activeDays: DayOfWeek[];
830
+ }
831
+ interface ScheduleInput {
832
+ rrule?: string | null;
833
+ intervalMinutes?: number | null;
834
+ scheduleTimeSlots?: ScheduleTimeSlot[];
835
+ }
836
+ /**
837
+ * Extract schedule information from a schedule object.
838
+ * Returns time range and active days for display purposes.
839
+ *
840
+ * @param schedule - Schedule object with rrule, intervalMinutes, and scheduleTimeSlots
841
+ * @returns ScheduleInfo with timeRange and activeDays
842
+ */
843
+ declare function getScheduleInfo(schedule: ScheduleInput | null | undefined): ScheduleInfo;
844
+
768
845
  interface Order3000ClientConfig {
769
846
  clientId: string;
770
847
  clientSecret: string;
@@ -792,4 +869,4 @@ declare class Order3000Client {
792
869
  constructor(config: Order3000ClientConfig);
793
870
  }
794
871
 
795
- export { type AddToBasketRequest, type AddToBasketResponse, type Basket, type BasketItem, type BasketItemMenuItemRef, type BasketItemMetadata, type BasketStatus, type CropArea, type Currency, type Event, type EventPoster, type EventRow, type GetMenuOptions, type ListEventsOptions, type ListEventsResponse, type Menu, type MenuAsset, type MenuBeverage, type MenuDish, type MenuItem, type MenuItemRow, type MenuItemType, Order3000Client, type Order3000ClientConfig, type Promotion, type RealtimeConfig, type RealtimeEvent, type RealtimeSubscription, type RemoveFromBasketResponse, type Schedule, type ScheduleOverride, type ScheduleOverrideRow, type ScheduleRow, type SubscriptionOptions, type TimeSlot, type Unit };
872
+ export { type AddToBasketRequest, type AddToBasketResponse, type Basket, type BasketItem, type BasketItemMenuItemRef, type BasketItemMetadata, type BasketStatus, type CropArea, type Currency, type DayOfWeek, type Event, type EventByAccessor, type EventMenu, type EventPoster, type EventRow, type GetEventOptions, type GetMenuOptions, type ListEventsOptions, type ListEventsResponse, type Menu, type MenuAsset, type MenuBeverage, type MenuDish, type MenuItem, type MenuItemRow, type MenuItemType, Order3000Client, type Order3000ClientConfig, type Promotion, type RealtimeConfig, type RealtimeEvent, type RealtimeSubscription, type RemoveFromBasketResponse, type Schedule, type ScheduleInfo, type ScheduleOverride, type ScheduleOverrideRow, type ScheduleRow, type ScheduleTimeSlot, type ScheduleWithTimeSlots, type SubscriptionOptions, type TimeSlot, type Unit, getScheduleInfo };
package/dist/client.mjs CHANGED
@@ -213,6 +213,20 @@ class EventsResource extends BaseResource {
213
213
  async get(eventId) {
214
214
  return this.request("GET", `/${eventId}`);
215
215
  }
216
+ /**
217
+ * Get an event by accessor (slug)
218
+ * @param accessor - The event accessor (e.g., 'lunch-menu')
219
+ * @param options - Optional expand options
220
+ * @returns The event with optional schedule, timeSlots, menus, and posters
221
+ */
222
+ async getByAccessor(accessor, options) {
223
+ const queryString = this.buildQueryString(options);
224
+ return this.request("GET", `/${accessor}${queryString}`);
225
+ }
226
+ buildQueryString(options) {
227
+ if (!options?.expand?.length) return "";
228
+ return `?expand=${options.expand.join(",")}`;
229
+ }
216
230
  }
217
231
 
218
232
  class MenusResource extends BaseResource {
@@ -484,6 +498,120 @@ class RealtimeManager {
484
498
  }
485
499
  }
486
500
 
501
+ const ALL_DAYS = [
502
+ "monday",
503
+ "tuesday",
504
+ "wednesday",
505
+ "thursday",
506
+ "friday",
507
+ "saturday",
508
+ "sunday"
509
+ ];
510
+ const RRULE_DAY_MAP = {
511
+ MO: "monday",
512
+ TU: "tuesday",
513
+ WE: "wednesday",
514
+ TH: "thursday",
515
+ FR: "friday",
516
+ SA: "saturday",
517
+ SU: "sunday"
518
+ };
519
+ function parseDaysFromRRule(rrule) {
520
+ if (!rrule) {
521
+ return [];
522
+ }
523
+ const byDayMatch = rrule.match(/BYDAY=([^;]+)/);
524
+ if (!byDayMatch) {
525
+ return [];
526
+ }
527
+ const rruleDays = byDayMatch[1].split(",");
528
+ const days = [];
529
+ for (const rruleDay of rruleDays) {
530
+ const day = RRULE_DAY_MAP[rruleDay.trim()];
531
+ if (day) {
532
+ days.push(day);
533
+ }
534
+ }
535
+ return ALL_DAYS.filter((day) => days.includes(day));
536
+ }
537
+ function addMinutesToTime(time, minutes) {
538
+ const parts = time.split(":");
539
+ const hours = parseInt(parts[0], 10);
540
+ const mins = parseInt(parts[1], 10);
541
+ const totalMinutes = hours * 60 + mins + minutes;
542
+ const newHours = Math.floor(totalMinutes / 60) % 24;
543
+ const newMins = totalMinutes % 60;
544
+ return `${newHours.toString().padStart(2, "0")}:${newMins.toString().padStart(2, "0")}`;
545
+ }
546
+ function formatTime(time) {
547
+ const parts = time.split(":");
548
+ if (parts.length >= 2) {
549
+ return `${parts[0]}:${parts[1]}`;
550
+ }
551
+ return time;
552
+ }
553
+ function getScheduleInfo(schedule) {
554
+ const defaultData = {
555
+ timeRange: null,
556
+ activeDays: []
557
+ };
558
+ if (!schedule?.scheduleTimeSlots?.length) {
559
+ return defaultData;
560
+ }
561
+ const timeSlots = schedule.scheduleTimeSlots;
562
+ const rrule = schedule.rrule;
563
+ const intervalMinutes = schedule.intervalMinutes ?? 30;
564
+ const activeDaysSet = /* @__PURE__ */ new Set();
565
+ let hasNullDayOfWeek = false;
566
+ const startTimes = [];
567
+ let latestEndTime = null;
568
+ for (const slot of timeSlots) {
569
+ if (slot.dayOfWeek) {
570
+ activeDaysSet.add(slot.dayOfWeek);
571
+ } else {
572
+ hasNullDayOfWeek = true;
573
+ }
574
+ if (slot.timeSlot.startTime) {
575
+ startTimes.push(slot.timeSlot.startTime);
576
+ }
577
+ if (slot.timeSlot.endTime) {
578
+ if (!latestEndTime || slot.timeSlot.endTime > latestEndTime) {
579
+ latestEndTime = slot.timeSlot.endTime;
580
+ }
581
+ }
582
+ }
583
+ let activeDays;
584
+ if (hasNullDayOfWeek) {
585
+ const rruleDays = parseDaysFromRRule(rrule);
586
+ if (rruleDays.length > 0) {
587
+ activeDays = rruleDays;
588
+ } else {
589
+ activeDays = ALL_DAYS.filter((day) => activeDaysSet.has(day));
590
+ }
591
+ } else {
592
+ activeDays = ALL_DAYS.filter((day) => activeDaysSet.has(day));
593
+ }
594
+ let timeRange = null;
595
+ if (startTimes.length > 0) {
596
+ startTimes.sort();
597
+ const earliestStart = startTimes[0];
598
+ const latestStart = startTimes[startTimes.length - 1];
599
+ let endTime;
600
+ if (latestEndTime) {
601
+ endTime = latestEndTime;
602
+ } else {
603
+ endTime = addMinutesToTime(latestStart, intervalMinutes);
604
+ }
605
+ const startFormatted = formatTime(earliestStart);
606
+ const endFormatted = formatTime(endTime);
607
+ timeRange = `${startFormatted}-${endFormatted}`;
608
+ }
609
+ return {
610
+ timeRange,
611
+ activeDays
612
+ };
613
+ }
614
+
487
615
  var __defProp = Object.defineProperty;
488
616
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
489
617
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -517,4 +645,4 @@ class Order3000Client {
517
645
  }
518
646
  }
519
647
 
520
- export { Order3000Client };
648
+ export { Order3000Client, getScheduleInfo };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "order3000",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "order3000 node.js sdk",
5
5
  "main": "./dist/client.cjs",
6
6
  "module": "./dist/client.mjs",
@@ -29,9 +29,9 @@
29
29
  "prettier": "^3.7.4",
30
30
  "tsx": "^4.19.2",
31
31
  "typescript": "^5.9.3",
32
+ "@kolaveri/prettier-config": "1.0.6",
32
33
  "@kolaveri/eslint-config": "1.0.9",
33
- "@kolaveri/tsconfig": "1.0.1",
34
- "@kolaveri/prettier-config": "1.0.6"
34
+ "@kolaveri/tsconfig": "1.0.1"
35
35
  },
36
36
  "files": [
37
37
  "dist"