@happychef/algorithm 1.2.28 → 1.2.29
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/bundle_entry.js +100 -0
- package/moment-timezone-shim.js +179 -0
- package/package.json +1 -1
package/bundle_entry.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// bundle_entry.js - Entry point for esbuild bundling
|
|
2
|
+
// Exposes all @happychef/algorithm functions on globalThis.HappyAlgorithm
|
|
3
|
+
// for use with flutter_js (QuickJS / JavaScriptCore)
|
|
4
|
+
|
|
5
|
+
const algorithm = require('./index.js');
|
|
6
|
+
|
|
7
|
+
// Intl.DateTimeFormat polyfill for QuickJS (which lacks Intl support)
|
|
8
|
+
if (typeof globalThis.Intl === 'undefined' || typeof globalThis.Intl.DateTimeFormat === 'undefined') {
|
|
9
|
+
// EU DST rules for Europe/Brussels
|
|
10
|
+
function getBrusselsOffsetHours(date) {
|
|
11
|
+
const year = date.getUTCFullYear();
|
|
12
|
+
const marchLast = new Date(Date.UTC(year, 2, 31));
|
|
13
|
+
const marchSunday = 31 - marchLast.getUTCDay();
|
|
14
|
+
const dstStart = Date.UTC(year, 2, marchSunday, 1, 0, 0);
|
|
15
|
+
const octLast = new Date(Date.UTC(year, 9, 31));
|
|
16
|
+
const octSunday = 31 - octLast.getUTCDay();
|
|
17
|
+
const dstEnd = Date.UTC(year, 9, octSunday, 1, 0, 0);
|
|
18
|
+
const ts = date.getTime();
|
|
19
|
+
return (ts >= dstStart && ts < dstEnd) ? 2 : 1;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!globalThis.Intl) globalThis.Intl = {};
|
|
23
|
+
|
|
24
|
+
globalThis.Intl.DateTimeFormat = function IntlDateTimeFormat(locale, options) {
|
|
25
|
+
this._options = options || {};
|
|
26
|
+
this.formatToParts = function(date) {
|
|
27
|
+
const d = date || new Date();
|
|
28
|
+
const tz = (this._options.timeZone || '').replace(/\//g, '/');
|
|
29
|
+
// Only support Europe/Brussels
|
|
30
|
+
const offset = getBrusselsOffsetHours(d);
|
|
31
|
+
const brusselsDate = new Date(d.getTime() + offset * 60 * 60 * 1000);
|
|
32
|
+
const parts = [];
|
|
33
|
+
if (this._options.hour) {
|
|
34
|
+
parts.push({ type: 'hour', value: String(brusselsDate.getUTCHours()).padStart(2, '0') });
|
|
35
|
+
}
|
|
36
|
+
if (this._options.minute) {
|
|
37
|
+
parts.push({ type: 'literal', value: ':' });
|
|
38
|
+
parts.push({ type: 'minute', value: String(brusselsDate.getUTCMinutes()).padStart(2, '0') });
|
|
39
|
+
}
|
|
40
|
+
return parts;
|
|
41
|
+
};
|
|
42
|
+
this.format = function(date) {
|
|
43
|
+
return this.formatToParts(date).map(function(p) { return p.value; }).join('');
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Expose all algorithm functions globally
|
|
49
|
+
globalThis.HappyAlgorithm = {
|
|
50
|
+
// Core availability functions
|
|
51
|
+
getAvailableTimeblocks: algorithm.getAvailableTimeblocks,
|
|
52
|
+
isDateAvailable: algorithm.isDateAvailable,
|
|
53
|
+
isDateAvailableWithTableCheck: algorithm.isDateAvailableWithTableCheck,
|
|
54
|
+
isTimeAvailable: algorithm.isTimeAvailable,
|
|
55
|
+
|
|
56
|
+
// Table assignment functions
|
|
57
|
+
isTimeAvailableSync: algorithm.isTimeAvailableSync,
|
|
58
|
+
filterTimeblocksByTableAvailability: algorithm.filterTimeblocksByTableAvailability,
|
|
59
|
+
getAvailableTimeblocksWithTableCheck: algorithm.getAvailableTimeblocksWithTableCheck,
|
|
60
|
+
getAvailableTablesForTime: algorithm.getAvailableTablesForTime,
|
|
61
|
+
|
|
62
|
+
// Processing functions
|
|
63
|
+
timeblocksAvailable: algorithm.timeblocksAvailable,
|
|
64
|
+
getDailyGuestCounts: algorithm.getDailyGuestCounts,
|
|
65
|
+
|
|
66
|
+
// Filter functions
|
|
67
|
+
filterTimeblocksByStopTimes: algorithm.filterTimeblocksByStopTimes,
|
|
68
|
+
filterTimeblocksByMaxArrivals: algorithm.filterTimeblocksByMaxArrivals,
|
|
69
|
+
filterTimeblocksByMaxGroups: algorithm.filterTimeblocksByMaxGroups,
|
|
70
|
+
|
|
71
|
+
// Table helpers
|
|
72
|
+
parseTime: algorithm.parseTime,
|
|
73
|
+
getMealTypeByTime: algorithm.getMealTypeByTime,
|
|
74
|
+
getAllTables: algorithm.getAllTables,
|
|
75
|
+
getFloorIdForSeatPlace: algorithm.getFloorIdForSeatPlace,
|
|
76
|
+
isTemporaryTableValid: algorithm.isTemporaryTableValid,
|
|
77
|
+
|
|
78
|
+
// Grouping
|
|
79
|
+
tryGroupTables: algorithm.tryGroupTables,
|
|
80
|
+
|
|
81
|
+
// Batch functions for calendar performance (avoid 30 separate JSON serializations)
|
|
82
|
+
batchIsDateAvailable: function(data, dates, reservations, guests, blockedSlots, giftcard, isAdmin, duration) {
|
|
83
|
+
var result = {};
|
|
84
|
+
for (var i = 0; i < dates.length; i++) {
|
|
85
|
+
result[dates[i]] = algorithm.isDateAvailable(data, dates[i], reservations, guests, blockedSlots, giftcard, isAdmin, duration);
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
batchIsDateAvailableWithTableCheck: function(data, dates, reservations, guests, blockedSlots, selectedGiftcard, isAdmin, duration, selectedZitplaats) {
|
|
91
|
+
var result = {};
|
|
92
|
+
for (var i = 0; i < dates.length; i++) {
|
|
93
|
+
result[dates[i]] = algorithm.isDateAvailableWithTableCheck(data, dates[i], reservations, guests, blockedSlots, selectedGiftcard, isAdmin, duration, selectedZitplaats);
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
// Version info
|
|
99
|
+
VERSION: '1.2.28'
|
|
100
|
+
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// Minimal moment-timezone shim for Europe/Brussels only
|
|
2
|
+
// Replaces the full ~500KB moment-timezone library
|
|
3
|
+
// Implements only the subset used by @happychef/algorithm
|
|
4
|
+
|
|
5
|
+
const TIMEZONE = 'Europe/Brussels';
|
|
6
|
+
|
|
7
|
+
// EU DST rules: CET (UTC+1) / CEST (UTC+2)
|
|
8
|
+
// CEST starts last Sunday of March at 02:00 UTC
|
|
9
|
+
// CET starts last Sunday of October at 03:00 UTC
|
|
10
|
+
function getBrusselsOffset(date) {
|
|
11
|
+
const year = date.getUTCFullYear();
|
|
12
|
+
const month = date.getUTCMonth(); // 0-indexed
|
|
13
|
+
|
|
14
|
+
// Find last Sunday of March
|
|
15
|
+
const marchLast = new Date(Date.UTC(year, 2, 31));
|
|
16
|
+
const marchSunday = 31 - marchLast.getUTCDay();
|
|
17
|
+
const dstStart = Date.UTC(year, 2, marchSunday, 1, 0, 0); // 02:00 CET = 01:00 UTC
|
|
18
|
+
|
|
19
|
+
// Find last Sunday of October
|
|
20
|
+
const octLast = new Date(Date.UTC(year, 9, 31));
|
|
21
|
+
const octSunday = 31 - octLast.getUTCDay();
|
|
22
|
+
const dstEnd = Date.UTC(year, 9, octSunday, 1, 0, 0); // 03:00 CEST = 01:00 UTC
|
|
23
|
+
|
|
24
|
+
const ts = date.getTime();
|
|
25
|
+
if (ts >= dstStart && ts < dstEnd) {
|
|
26
|
+
return 2; // CEST (UTC+2)
|
|
27
|
+
}
|
|
28
|
+
return 1; // CET (UTC+1)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function toBrusselsDate(date) {
|
|
32
|
+
const offset = getBrusselsOffset(date);
|
|
33
|
+
return new Date(date.getTime() + offset * 60 * 60 * 1000);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function createMomentObject(date, offset) {
|
|
37
|
+
const brusselsDate = new Date(date.getTime() + offset * 60 * 60 * 1000);
|
|
38
|
+
|
|
39
|
+
const obj = {
|
|
40
|
+
_date: date,
|
|
41
|
+
_brusselsDate: brusselsDate,
|
|
42
|
+
_offset: offset,
|
|
43
|
+
_valid: true,
|
|
44
|
+
|
|
45
|
+
isValid() {
|
|
46
|
+
return this._valid;
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
day() {
|
|
50
|
+
return this._brusselsDate.getUTCDay();
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
hours() {
|
|
54
|
+
return this._brusselsDate.getUTCHours();
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
minutes() {
|
|
58
|
+
return this._brusselsDate.getUTCMinutes();
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
format(fmt) {
|
|
62
|
+
if (fmt === 'YYYY-MM-DD') {
|
|
63
|
+
const y = this._brusselsDate.getUTCFullYear();
|
|
64
|
+
const m = String(this._brusselsDate.getUTCMonth() + 1).padStart(2, '0');
|
|
65
|
+
const d = String(this._brusselsDate.getUTCDate()).padStart(2, '0');
|
|
66
|
+
return `${y}-${m}-${d}`;
|
|
67
|
+
}
|
|
68
|
+
if (fmt === 'HH:mm') {
|
|
69
|
+
const h = String(this._brusselsDate.getUTCHours()).padStart(2, '0');
|
|
70
|
+
const min = String(this._brusselsDate.getUTCMinutes()).padStart(2, '0');
|
|
71
|
+
return `${h}:${min}`;
|
|
72
|
+
}
|
|
73
|
+
return this._brusselsDate.toISOString();
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
startOf(unit) {
|
|
77
|
+
if (unit === 'day') {
|
|
78
|
+
const d = new Date(Date.UTC(
|
|
79
|
+
this._brusselsDate.getUTCFullYear(),
|
|
80
|
+
this._brusselsDate.getUTCMonth(),
|
|
81
|
+
this._brusselsDate.getUTCDate(),
|
|
82
|
+
0, 0, 0, 0
|
|
83
|
+
));
|
|
84
|
+
// Adjust back from Brussels to UTC
|
|
85
|
+
const utcDate = new Date(d.getTime() - this._offset * 60 * 60 * 1000);
|
|
86
|
+
return createMomentObject(utcDate, this._offset);
|
|
87
|
+
}
|
|
88
|
+
return this;
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
endOf(unit) {
|
|
92
|
+
if (unit === 'day') {
|
|
93
|
+
const d = new Date(Date.UTC(
|
|
94
|
+
this._brusselsDate.getUTCFullYear(),
|
|
95
|
+
this._brusselsDate.getUTCMonth(),
|
|
96
|
+
this._brusselsDate.getUTCDate(),
|
|
97
|
+
23, 59, 59, 999
|
|
98
|
+
));
|
|
99
|
+
const utcDate = new Date(d.getTime() - this._offset * 60 * 60 * 1000);
|
|
100
|
+
return createMomentObject(utcDate, this._offset);
|
|
101
|
+
}
|
|
102
|
+
return this;
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
isBefore(other) {
|
|
106
|
+
return this._date.getTime() < other._date.getTime();
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
isAfter(other) {
|
|
110
|
+
return this._date.getTime() > other._date.getTime();
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
tz() {
|
|
114
|
+
// Already in Brussels timezone, return self
|
|
115
|
+
return this;
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
return obj;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function parseDateStr(dateStr, format) {
|
|
123
|
+
if (format === 'YYYY-MM-DD') {
|
|
124
|
+
const parts = dateStr.split('-');
|
|
125
|
+
if (parts.length !== 3) return null;
|
|
126
|
+
const year = parseInt(parts[0], 10);
|
|
127
|
+
const month = parseInt(parts[1], 10) - 1;
|
|
128
|
+
const day = parseInt(parts[2], 10);
|
|
129
|
+
if (isNaN(year) || isNaN(month) || isNaN(day)) return null;
|
|
130
|
+
if (month < 0 || month > 11 || day < 1 || day > 31) return null;
|
|
131
|
+
// Create date at midnight Brussels time -> convert to UTC
|
|
132
|
+
const utcDate = new Date(Date.UTC(year, month, day, 0, 0, 0));
|
|
133
|
+
return utcDate;
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Main moment function
|
|
139
|
+
function moment(dateStr, format, timezone) {
|
|
140
|
+
if (dateStr === undefined || dateStr === null) {
|
|
141
|
+
// moment() - current time
|
|
142
|
+
const now = new Date();
|
|
143
|
+
const offset = getBrusselsOffset(now);
|
|
144
|
+
const obj = createMomentObject(now, offset);
|
|
145
|
+
obj.tz = function() { return obj; };
|
|
146
|
+
return obj;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (typeof dateStr === 'string') {
|
|
150
|
+
const date = parseDateStr(dateStr, format || 'YYYY-MM-DD');
|
|
151
|
+
if (!date) {
|
|
152
|
+
return { _valid: false, isValid() { return false; }, day() { return 0; }, tz() { return this; } };
|
|
153
|
+
}
|
|
154
|
+
const offset = getBrusselsOffset(date);
|
|
155
|
+
return createMomentObject(date, offset);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Fallback
|
|
159
|
+
const now = new Date();
|
|
160
|
+
const offset = getBrusselsOffset(now);
|
|
161
|
+
return createMomentObject(now, offset);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// moment.tz(dateStr, format, timezone) or moment().tz(timezone)
|
|
165
|
+
moment.tz = function(dateStr, format, timezone) {
|
|
166
|
+
if (typeof dateStr === 'string' && typeof format === 'string' && typeof timezone === 'string') {
|
|
167
|
+
// moment.tz(dateStr, format, timezone)
|
|
168
|
+
return moment(dateStr, format, timezone);
|
|
169
|
+
}
|
|
170
|
+
if (typeof dateStr === 'string' && typeof format === 'string' && timezone === undefined) {
|
|
171
|
+
// moment.tz(dateStr, timezone) - dateStr is actual date, format is timezone
|
|
172
|
+
// This pattern: moment().tz('Europe/Brussels')
|
|
173
|
+
return moment(dateStr, 'YYYY-MM-DD');
|
|
174
|
+
}
|
|
175
|
+
// Fallback: current time in Brussels
|
|
176
|
+
return moment();
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
module.exports = moment;
|