@curless/hotel-storefront 0.46.0 → 0.47.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/card.generated.d.ts +1 -1
- package/dist/card.generated.js +2 -2
- package/dist/card.generated.js.map +1 -1
- package/dist/demo-hotels.d.ts.map +1 -1
- package/dist/demo-hotels.js +6 -1
- package/dist/demo-hotels.js.map +1 -1
- package/dist/huazhu/catalog.d.ts +9 -2
- package/dist/huazhu/catalog.d.ts.map +1 -1
- package/dist/huazhu/catalog.js +65 -5
- package/dist/huazhu/catalog.js.map +1 -1
- package/dist/huazhu/english.d.ts +8 -0
- package/dist/huazhu/english.d.ts.map +1 -1
- package/dist/huazhu/english.js +295 -2
- package/dist/huazhu/english.js.map +1 -1
- package/dist/room-filters.d.ts +37 -7
- package/dist/room-filters.d.ts.map +1 -1
- package/dist/room-filters.js +82 -21
- package/dist/room-filters.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.js +2 -2
- package/dist/tools.d.ts +14 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +89 -4
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/room-filters.js
CHANGED
|
@@ -1,10 +1,31 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The four a hotel's chip row ALWAYS has - a guest looks for these on every
|
|
3
|
+
* hotel, and a chip that is gone says nothing, where one marked 0 says the
|
|
4
|
+
* hotel has none (robin, 2026-10-23).
|
|
5
|
+
*/
|
|
6
|
+
export const CORE_FILTER_KEYS = [
|
|
3
7
|
'breakfast',
|
|
4
8
|
'king',
|
|
5
9
|
'twin',
|
|
6
10
|
'freeCancellation',
|
|
7
11
|
];
|
|
12
|
+
/**
|
|
13
|
+
* The ones that are offered only where a hotel's rooms DIFFER in them: a chip
|
|
14
|
+
* for a window every room has (or none has) narrows nothing.
|
|
15
|
+
*/
|
|
16
|
+
export const SPLIT_FILTER_KEYS = [
|
|
17
|
+
'window',
|
|
18
|
+
'payAtHotel',
|
|
19
|
+
'payOnline',
|
|
20
|
+
'family',
|
|
21
|
+
];
|
|
22
|
+
/** In the order a chip row shows them. */
|
|
23
|
+
export const ROOM_FILTER_KEYS = [
|
|
24
|
+
...CORE_FILTER_KEYS,
|
|
25
|
+
...SPLIT_FILTER_KEYS,
|
|
26
|
+
];
|
|
27
|
+
/** A room that sleeps this many is a family room: 家庭房, "Sleeps 3+". */
|
|
28
|
+
export const FAMILY_SLEEPS = 3;
|
|
8
29
|
/**
|
|
9
30
|
* Two ways of reading a bed in words. A QUEEN COUNTS WITH THE KING: "king" is
|
|
10
31
|
* the large-bed filter - one big bed for two, which is what a guest who says
|
|
@@ -119,7 +140,14 @@ export const breakfastOf = (room) => {
|
|
|
119
140
|
* way). A room by the hour has no cancellation terms to speak of.
|
|
120
141
|
*/
|
|
121
142
|
export const freeCancellationOf = (room) => !room.hourly && room.refundable && !!room.freeCancellationUntil;
|
|
122
|
-
/**
|
|
143
|
+
/**
|
|
144
|
+
* Everything a card needs to know about one room to filter it.
|
|
145
|
+
*
|
|
146
|
+
* ⚠️ A WINDOW IS 'yes' AND NOTHING ELSE (robin, 2026-10-23): a partly-windowed
|
|
147
|
+
* room, an inner window onto a light well, a room with none, and a room whose
|
|
148
|
+
* data says nothing are not "has a window". A room that says nothing of how it
|
|
149
|
+
* is paid is neither at the hotel nor online - the card does not guess.
|
|
150
|
+
*/
|
|
123
151
|
export const facetsOf = (room) => {
|
|
124
152
|
const beds = bedKindsOf(room);
|
|
125
153
|
return {
|
|
@@ -127,49 +155,82 @@ export const facetsOf = (room) => {
|
|
|
127
155
|
king: beds.king,
|
|
128
156
|
twin: beds.twin,
|
|
129
157
|
freeCancellation: freeCancellationOf(room),
|
|
158
|
+
window: room.window === 'yes',
|
|
159
|
+
payAtHotel: room.payment === 'at-hotel',
|
|
160
|
+
payOnline: room.payment === 'prepaid',
|
|
161
|
+
family: room.sleeps >= FAMILY_SLEEPS,
|
|
130
162
|
};
|
|
131
163
|
};
|
|
132
|
-
/** The terms a call asked for, or undefined when it asked for none. Only `true` narrows. */
|
|
164
|
+
/** The terms a call asked for, or undefined when it asked for none. Only `true` (or a payment given) narrows. */
|
|
133
165
|
export const roomTermsOf = (args) => {
|
|
134
166
|
const terms = {
|
|
135
167
|
...(args.bed === 'king' || args.bed === 'twin' ? { bed: args.bed } : {}),
|
|
136
168
|
...(args.breakfast === true ? { breakfast: true } : {}),
|
|
137
169
|
...(args.freeCancellation === true ? { freeCancellation: true } : {}),
|
|
170
|
+
...(args.window === true ? { window: true } : {}),
|
|
171
|
+
...(args.payment === 'at-hotel' || args.payment === 'online' ? { payment: args.payment } : {}),
|
|
172
|
+
...(args.family === true ? { family: true } : {}),
|
|
138
173
|
};
|
|
139
174
|
return Object.keys(terms).length ? terms : undefined;
|
|
140
175
|
};
|
|
176
|
+
/** Whether the terms switch this chip on. The two beds, and the two ways to pay, are one choice each. */
|
|
177
|
+
const termsHave = (terms, k) => {
|
|
178
|
+
if (!terms)
|
|
179
|
+
return false;
|
|
180
|
+
switch (k) {
|
|
181
|
+
case 'king':
|
|
182
|
+
case 'twin':
|
|
183
|
+
return terms.bed === k;
|
|
184
|
+
case 'payAtHotel':
|
|
185
|
+
return terms.payment === 'at-hotel';
|
|
186
|
+
case 'payOnline':
|
|
187
|
+
return terms.payment === 'online';
|
|
188
|
+
default:
|
|
189
|
+
return !!terms[k];
|
|
190
|
+
}
|
|
191
|
+
};
|
|
141
192
|
/** The terms as the chip keys they switch on - the order a chip row shows them. */
|
|
142
|
-
export const activeKeysOf = (terms) => ROOM_FILTER_KEYS.filter((k) =>
|
|
143
|
-
? terms?.bed === k
|
|
144
|
-
: !!terms?.[k]);
|
|
193
|
+
export const activeKeysOf = (terms) => ROOM_FILTER_KEYS.filter((k) => termsHave(terms, k));
|
|
145
194
|
/** Whether a room has everything the terms ask for. */
|
|
146
195
|
export const matchesTerms = (room, terms) => {
|
|
147
196
|
if (!terms)
|
|
148
197
|
return true;
|
|
149
198
|
const f = facetsOf(room);
|
|
150
|
-
return (
|
|
151
|
-
(!terms.breakfast || f.breakfast) &&
|
|
152
|
-
(!terms.freeCancellation || f.freeCancellation));
|
|
199
|
+
return activeKeysOf(terms).every((k) => f[k]);
|
|
153
200
|
};
|
|
154
201
|
/**
|
|
155
|
-
* The chips a hotel's rooms offer
|
|
156
|
-
*
|
|
157
|
-
*
|
|
202
|
+
* The chips a hotel's rooms offer, each with how many rooms (rates) it keeps
|
|
203
|
+
* on its own, in the order a chip row shows them.
|
|
204
|
+
*
|
|
205
|
+
* ⚠️ THE CORE FOUR ARE ALWAYS HERE, even at 0: a hotel with no twin room says
|
|
206
|
+
* so, and the card draws that chip empty and pressable. The rest are here ONLY
|
|
207
|
+
* WHERE THEY SPLIT the hotel's rooms - some have it and some do not. A window
|
|
208
|
+
* every room has, or none does, narrows nothing, and a row of chips that do
|
|
209
|
+
* nothing is noise.
|
|
158
210
|
*/
|
|
159
211
|
export const optionsOf = (rooms) => {
|
|
160
212
|
const all = rooms.map(facetsOf);
|
|
161
|
-
return ROOM_FILTER_KEYS.map((key) => ({ key, count: all.filter((f) => f[key]).length })).filter((o) => o.count > 0);
|
|
213
|
+
return ROOM_FILTER_KEYS.map((key) => ({ key, count: all.filter((f) => f[key]).length })).filter((o) => CORE_FILTER_KEYS.includes(o.key) || (o.count > 0 && o.count < all.length));
|
|
214
|
+
};
|
|
215
|
+
const KEY_WORDS = {
|
|
216
|
+
breakfast: 'breakfast included',
|
|
217
|
+
king: 'king bed',
|
|
218
|
+
twin: 'twin beds',
|
|
219
|
+
freeCancellation: 'free cancellation',
|
|
220
|
+
window: 'a window',
|
|
221
|
+
payAtHotel: 'payment at the hotel',
|
|
222
|
+
payOnline: 'payment online',
|
|
223
|
+
family: `room for ${FAMILY_SLEEPS} or more`,
|
|
162
224
|
};
|
|
225
|
+
const isBedKey = (k) => k === 'king' || k === 'twin';
|
|
163
226
|
/** The terms in words, for a sentence: "king bed, breakfast included, free cancellation". */
|
|
164
|
-
export const termWords = (terms) =>
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
]
|
|
169
|
-
.filter(Boolean)
|
|
227
|
+
export const termWords = (terms) => activeKeysOf(terms)
|
|
228
|
+
// The sentence has always said the bed first.
|
|
229
|
+
.sort((a, b) => Number(!isBedKey(a)) - Number(!isBedKey(b)))
|
|
230
|
+
.map((k) => KEY_WORDS[k])
|
|
170
231
|
.join(', ');
|
|
171
232
|
/** One chip in words, for a sentence. */
|
|
172
|
-
export const keyWords = (key) =>
|
|
233
|
+
export const keyWords = (key) => KEY_WORDS[key];
|
|
173
234
|
/**
|
|
174
235
|
* A hotel's rooms by room type, in the order the types first appear: a group
|
|
175
236
|
* that sells several rates on one type (Huazhu's 房型 × 房价码) shares a
|
package/dist/room-filters.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"room-filters.js","sourceRoot":"","sources":["../src/room-filters.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"room-filters.js","sourceRoot":"","sources":["../src/room-filters.ts"],"names":[],"mappings":"AA+BA;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA6B;IACxD,WAAW;IACX,MAAM;IACN,MAAM;IACN,kBAAkB;CACnB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA6B;IACzD,QAAQ;IACR,YAAY;IACZ,WAAW;IACX,QAAQ;CACT,CAAC;AAEF,0CAA0C;AAC1C,MAAM,CAAC,MAAM,gBAAgB,GAA6B;IACxD,GAAG,gBAAgB;IACnB,GAAG,iBAAiB;CACrB,CAAC;AAYF,uEAAuE;AACvE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAQ/B;;;;;GAKG;AACH,MAAM,KAAK,GAAG,mCAAmC,CAAC;AAClD,MAAM,IAAI,GAAG,gBAAgB,CAAC;AAC9B,gDAAgD;AAChD,MAAM,OAAO,GAAG,+BAA+B,CAAC;AAChD;;;;GAIG;AACH,MAAM,UAAU,GAAG,yBAAyB,CAAC;AAE7C,MAAM,SAAS,GAAG,CAAC,IAAY,EAAU,EAAE,CACzC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAE9E;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,CAAC,IAAY,EAAoC,EAAE;IACpE,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK;YAAE,IAAI,GAAG,IAAI,CAAC;QACvB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAAE,IAAI,GAAG,IAAI,CAAC;IACvE,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,CAAC,IAAY,EAAoC,EAAE;IACpE,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;QAC9C,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,IAAI,GAAG,IAAI,CAAC;QAC3C,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,IAAI,GAAG,IAAI,CAAC;IACnC,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC,CAAC;AAEF,6FAA6F;AAC7F,MAAM,WAAW,GAAG,CAAC,KAAgB,EAAoC,EAAE;IACzE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;IAChE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC;AACzF,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,IAA0F,EACxD,EAAE;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7E,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7D,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IAC1D,wFAAwF;IACxF,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ;QACzB,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC;QAC/C,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAChC,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC;QACpB,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC;IACtB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAiD,EAAW,EAAE;IACxF,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;IAChD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;IACjC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/D,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;AAC1B,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,IAAmE,EAC1D,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC;AAE9E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAU,EAAc,EAAE;IACjD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO;QACL,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC;QAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,gBAAgB,EAAE,kBAAkB,CAAC,IAAI,CAAC;QAC1C,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,KAAK;QAC7B,UAAU,EAAE,IAAI,CAAC,OAAO,KAAK,UAAU;QACvC,SAAS,EAAE,IAAI,CAAC,OAAO,KAAK,SAAS;QACrC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,aAAa;KACrC,CAAC;AACJ,CAAC,CAAC;AAEF,iHAAiH;AACjH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAA6B,EAAyB,EAAE;IAClF,MAAM,KAAK,GAAc;QACvB,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,IAAI,CAAC,gBAAgB,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9E,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,UAAU,IAAI,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9F,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3D,CAAC;IACF,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC,CAAC;AAEF,yGAAyG;AACzG,MAAM,SAAS,GAAG,CAAC,KAA4B,EAAE,CAAgB,EAAW,EAAE;IAC5E,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,QAAQ,CAAC,EAAE,CAAC;QACV,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM;YACT,OAAO,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC;QACzB,KAAK,YAAY;YACf,OAAO,KAAK,CAAC,OAAO,KAAK,UAAU,CAAC;QACtC,KAAK,WAAW;YACd,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC;QACpC;YACE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;AACH,CAAC,CAAC;AAEF,mFAAmF;AACnF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAA4B,EAAmB,EAAE,CAC5E,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AAEtD,uDAAuD;AACvD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAU,EAAE,KAA4B,EAAW,EAAE;IAChF,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACzB,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAa,EAAsB,EAAE;IAC7D,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChC,OAAO,gBAAgB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAC7F,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,CACjF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,SAAS,GAAkC;IAC/C,SAAS,EAAE,oBAAoB;IAC/B,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,WAAW;IACjB,gBAAgB,EAAE,mBAAmB;IACrC,MAAM,EAAE,UAAU;IAClB,UAAU,EAAE,sBAAsB;IAClC,SAAS,EAAE,gBAAgB;IAC3B,MAAM,EAAE,YAAY,aAAa,UAAU;CAC5C,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,CAAgB,EAAW,EAAE,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,MAAM,CAAC;AAE7E,6FAA6F;AAC7F,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAgB,EAAU,EAAE,CACpD,YAAY,CAAC,KAAK,CAAC;IACjB,8CAA8C;KAC7C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;KAC3D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;KACxB,IAAI,CAAC,IAAI,CAAC,CAAC;AAEhB,yCAAyC;AACzC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAkB,EAAU,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,KAAU,EACkC,EAAE;IAC9C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoD,CAAC;IAC1E,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3B,IAAI,IAAI;YAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;YACxB,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;AAC7B,CAAC,CAAC"}
|
package/dist/server.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export declare const INITIALIZE_PER_MINUTE = 300;
|
|
|
28
28
|
* number. Found by reading the boot banner of a container that had just been
|
|
29
29
|
* deployed (2026-09-22): seventeen tools listed, and "0.7.0" above them.
|
|
30
30
|
*/
|
|
31
|
-
export declare const VERSION = "0.
|
|
31
|
+
export declare const VERSION = "0.47.0";
|
|
32
32
|
/**
|
|
33
33
|
* The card's resource URI.
|
|
34
34
|
*
|
|
@@ -37,7 +37,7 @@ export declare const VERSION = "0.46.0";
|
|
|
37
37
|
* connector went storefront-v35 → v40 in a single day of UI work for exactly
|
|
38
38
|
* this reason.
|
|
39
39
|
*/
|
|
40
|
-
export declare const CARD_URI = "ui://curless/hotel/booking-
|
|
40
|
+
export declare const CARD_URI = "ui://curless/hotel/booking-v88.html";
|
|
41
41
|
/**
|
|
42
42
|
* The URI one deployment names its card by: `CARD_URI` with a short hash of
|
|
43
43
|
* everything a host caches under it - the card itself, and the hosts it may
|
package/dist/server.js
CHANGED
|
@@ -47,7 +47,7 @@ export const INITIALIZE_PER_MINUTE = 300;
|
|
|
47
47
|
* number. Found by reading the boot banner of a container that had just been
|
|
48
48
|
* deployed (2026-09-22): seventeen tools listed, and "0.7.0" above them.
|
|
49
49
|
*/
|
|
50
|
-
export const VERSION = '0.
|
|
50
|
+
export const VERSION = '0.47.0';
|
|
51
51
|
/**
|
|
52
52
|
* The card's resource URI.
|
|
53
53
|
*
|
|
@@ -56,7 +56,7 @@ export const VERSION = '0.46.0';
|
|
|
56
56
|
* connector went storefront-v35 → v40 in a single day of UI work for exactly
|
|
57
57
|
* this reason.
|
|
58
58
|
*/
|
|
59
|
-
export const CARD_URI = 'ui://curless/hotel/booking-
|
|
59
|
+
export const CARD_URI = 'ui://curless/hotel/booking-v88.html';
|
|
60
60
|
/** The card as it ships, hashed once - what a host caches under the URI. */
|
|
61
61
|
const CARD_HTML_SHA = createHash('sha256').update(HOTEL_CARD_HTML).digest('hex');
|
|
62
62
|
/**
|
package/dist/tools.d.ts
CHANGED
|
@@ -110,7 +110,7 @@ export declare const buildTools: (n: ToolNames, v: Vocabulary, caps?: BackendCap
|
|
|
110
110
|
};
|
|
111
111
|
} | {
|
|
112
112
|
readonly name: `get_${string}${string}`;
|
|
113
|
-
readonly description: `One ${string} in full: description, amenities, address, and check-in and check-out times where the ${string} publishes them. Given \`checkIn\` and \`checkOut\` it also returns the room types that can be booked for those nights, one line per type at its lowest rate: the nightly rate, the stay total including taxes and fees, whether it can be cancelled free and until when, and how many rates it has. \`rooms\` leaves out the types that have fewer than that many left. \`bed\`, \`breakfast\` and \`
|
|
113
|
+
readonly description: `One ${string} in full: description, amenities, address, and check-in and check-out times where the ${string} publishes them. Given \`checkIn\` and \`checkOut\` it also returns the room types that can be booked for those nights, one line per type at its lowest rate: the nightly rate, the stay total including taxes and fees, whether it can be cancelled free and until when, and how many rates it has. \`rooms\` leaves out the types that have fewer than that many left. \`bed\`, \`breakfast\`, \`freeCancellation\`, \`window\`, \`payment\` and \`family\` keep only the rates that meet all of those given; the card still holds every room, with the given filters selected. Without dates it returns the ${string} only, because a room has no price until the nights are known. The ${string} is drawn as a card for the guest to look at.${string}`;
|
|
114
114
|
readonly annotations: {
|
|
115
115
|
readonly title: string;
|
|
116
116
|
readonly readOnlyHint: true;
|
|
@@ -140,6 +140,19 @@ export declare const buildTools: (n: ToolNames, v: Vocabulary, caps?: BackendCap
|
|
|
140
140
|
readonly type: "boolean";
|
|
141
141
|
readonly description: "With dates: only rooms that can be cancelled free";
|
|
142
142
|
};
|
|
143
|
+
readonly window: {
|
|
144
|
+
readonly type: "boolean";
|
|
145
|
+
readonly description: "With dates: only rooms with a window (not a partial or an inner one)";
|
|
146
|
+
};
|
|
147
|
+
readonly payment: {
|
|
148
|
+
readonly type: "string";
|
|
149
|
+
readonly enum: readonly ["at-hotel", "online"];
|
|
150
|
+
readonly description: "With dates: only rooms paid at the hotel (`at-hotel`) or in advance online (`online`)";
|
|
151
|
+
};
|
|
152
|
+
readonly family: {
|
|
153
|
+
readonly type: "boolean";
|
|
154
|
+
readonly description: "With dates: only rooms that sleep 3 or more";
|
|
155
|
+
};
|
|
143
156
|
readonly checkIn: {
|
|
144
157
|
readonly type: "string";
|
|
145
158
|
readonly pattern: "^\\d{4}-\\d{2}-\\d{2}$";
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,mBAAmB,EASzB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAa,YAAY,EAAgB,MAAM,cAAc,CAAC;AAC1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAK7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AA8BhD,OAAO,EAGL,KAAK,SAAS,EAIf,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAEV,cAAc,EAkBd,eAAe,EAKhB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAa,KAAK,UAAU,EAAwC,MAAM,YAAY,CAAC;AAuF9F,+GAA+G;AAC/G,eAAO,MAAM,WAAW,IAAI,CAAC;AAE7B;;;;GAIG;AACH,eAAO,MAAM,UAAU,GACrB,GAAG,SAAS,EACZ,GAAG,UAAU,EACb,OAAM,mBAAuC
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/dist/tools.js
CHANGED
|
@@ -339,7 +339,7 @@ const allTools = (n, v) => {
|
|
|
339
339
|
},
|
|
340
340
|
{
|
|
341
341
|
name: n.getHotel,
|
|
342
|
-
description: `One ${v.noun} in full: description, amenities, address, and check-in and check-out times where the ${v.noun} publishes them. Given \`checkIn\` and \`checkOut\` it also returns the room types that can be booked for those nights, one line per type at its lowest rate: the nightly rate, the stay total including taxes and fees, whether it can be cancelled free and until when, and how many rates it has. \`rooms\` leaves out the types that have fewer than that many left. \`bed\`, \`breakfast\` and \`
|
|
342
|
+
description: `One ${v.noun} in full: description, amenities, address, and check-in and check-out times where the ${v.noun} publishes them. Given \`checkIn\` and \`checkOut\` it also returns the room types that can be booked for those nights, one line per type at its lowest rate: the nightly rate, the stay total including taxes and fees, whether it can be cancelled free and until when, and how many rates it has. \`rooms\` leaves out the types that have fewer than that many left. \`bed\`, \`breakfast\`, \`freeCancellation\`, \`window\`, \`payment\` and \`family\` keep only the rates that meet all of those given; the card still holds every room, with the given filters selected. Without dates it returns the ${v.noun} only, because a room has no price until the nights are known. The ${v.noun} is drawn as a card for the guest to look at.${v.hints.hotel ? ` ${v.hints.hotel}` : ''}`,
|
|
343
343
|
annotations: reads(`View one ${catalogue(v, true)}`, open),
|
|
344
344
|
inputSchema: {
|
|
345
345
|
type: 'object',
|
|
@@ -368,6 +368,19 @@ const allTools = (n, v) => {
|
|
|
368
368
|
type: 'boolean',
|
|
369
369
|
description: 'With dates: only rooms that can be cancelled free',
|
|
370
370
|
},
|
|
371
|
+
window: {
|
|
372
|
+
type: 'boolean',
|
|
373
|
+
description: 'With dates: only rooms with a window (not a partial or an inner one)',
|
|
374
|
+
},
|
|
375
|
+
payment: {
|
|
376
|
+
type: 'string',
|
|
377
|
+
enum: ['at-hotel', 'online'],
|
|
378
|
+
description: 'With dates: only rooms paid at the hotel (`at-hotel`) or in advance online (`online`)',
|
|
379
|
+
},
|
|
380
|
+
family: {
|
|
381
|
+
type: 'boolean',
|
|
382
|
+
description: 'With dates: only rooms that sleep 3 or more',
|
|
383
|
+
},
|
|
371
384
|
},
|
|
372
385
|
required: ['hotel'],
|
|
373
386
|
},
|
|
@@ -1050,12 +1063,22 @@ const HOTEL_PAGE = {
|
|
|
1050
1063
|
dates: ARR,
|
|
1051
1064
|
/**
|
|
1052
1065
|
* The room filters this hotel's rooms offer, each with how many rooms (rates)
|
|
1053
|
-
* it keeps - `{ key
|
|
1054
|
-
*
|
|
1066
|
+
* it keeps - `{ key, count }`, `key` one of `breakfast`, `king`, `twin`,
|
|
1067
|
+
* `freeCancellation` (always here, `count` 0 where no room has it) and
|
|
1068
|
+
* `window`, `payAtHotel`, `payOnline`, `family` (here only where some rooms
|
|
1069
|
+
* have it and some do not).
|
|
1055
1070
|
*/
|
|
1056
1071
|
roomFilters: ARR,
|
|
1057
1072
|
/** The filters the call asked for, as the same keys - the card opens with these selected. */
|
|
1058
1073
|
activeFilters: STRS,
|
|
1074
|
+
/**
|
|
1075
|
+
* Room types with no room to book for these nights (none left, or fewer
|
|
1076
|
+
* than the rooms asked for): `{ id, name, names?, sleeps, ..., left? }`, no
|
|
1077
|
+
* price. The card draws them muted at the end of the list, so a type the
|
|
1078
|
+
* guest saw is said to be sold out and not left out. Absent where there are
|
|
1079
|
+
* none - and never in what the assistant is told.
|
|
1080
|
+
*/
|
|
1081
|
+
soldOut: ARR,
|
|
1059
1082
|
};
|
|
1060
1083
|
export const buildOutputSchemas = (n) => ({
|
|
1061
1084
|
[n.listHotels]: {
|
|
@@ -1173,6 +1196,8 @@ export const buildOutputSchemas = (n) => ({
|
|
|
1173
1196
|
accessibility: BOOL,
|
|
1174
1197
|
/** One per stay, when the trip held several. */
|
|
1175
1198
|
bookings: ARR,
|
|
1199
|
+
/** What all of `bookings` come to, where they are in one currency (the card's first screen). */
|
|
1200
|
+
totalAll: STR,
|
|
1176
1201
|
/**
|
|
1177
1202
|
* The stays that could not be booked when the others were - each with
|
|
1178
1203
|
* why, still in the trip, and what could be booked instead (robin,
|
|
@@ -2068,7 +2093,7 @@ when, enough, roomsWanted, terms) => {
|
|
|
2068
2093
|
...roomTypeLines(rs, roomsWanted, terms),
|
|
2069
2094
|
...(byRoomType(rs).some((t) => t.rooms.length > 1)
|
|
2070
2095
|
? [
|
|
2071
|
-
'A type with several rates is priced from its cheapest one; bed, breakfast and
|
|
2096
|
+
'A type with several rates is priced from its cheapest one; bed, breakfast, freeCancellation, window, payment and family narrow to the others (the card lists every rate).',
|
|
2072
2097
|
]
|
|
2073
2098
|
: []),
|
|
2074
2099
|
];
|
|
@@ -2221,6 +2246,52 @@ const dateFlex = (dates, stay) => {
|
|
|
2221
2246
|
text: `Arriving ${beats.checkIn} instead is ${formatMoney(saved)} less for ${sameNights}.`,
|
|
2222
2247
|
};
|
|
2223
2248
|
};
|
|
2249
|
+
/**
|
|
2250
|
+
* The room types a guest can no longer book on these nights - for the card to
|
|
2251
|
+
* say so, and not leave them out (r10 #10: a type the guest saw earlier
|
|
2252
|
+
* vanished from the list, and the heading counted one fewer, without a word).
|
|
2253
|
+
*
|
|
2254
|
+
* ⚠️ AN ADDITIVE FIELD, NEVER THE TEXT. What the assistant is told is the rooms
|
|
2255
|
+
* that can be booked, as before; this is only what the card draws, muted, at
|
|
2256
|
+
* the end of the list. A type is listed when
|
|
2257
|
+
* - the backend sends it with none left (`HotelDetail.soldOut`, or a room with
|
|
2258
|
+
* `roomsLeft: 0`), or
|
|
2259
|
+
* - it has some left, but fewer than the rooms asked for (`left`): a guest who
|
|
2260
|
+
* asked for two rooms and was shown no type with one left was not told why.
|
|
2261
|
+
* Not a type that sleeps fewer than the party (the backend never sends it), and
|
|
2262
|
+
* not a type any of whose rates can be booked. One entry a type, with the facts
|
|
2263
|
+
* the card says of a room and no price.
|
|
2264
|
+
*/
|
|
2265
|
+
const soldOutTypesOf = (detail, enough, wanted) => {
|
|
2266
|
+
const key = (r) => r.roomType?.id ?? r.id;
|
|
2267
|
+
const open = new Set(enough.map(key));
|
|
2268
|
+
const types = new Map();
|
|
2269
|
+
for (const r of [...(detail.rooms ?? []), ...(detail.soldOut ?? [])]) {
|
|
2270
|
+
if (r.hourly || open.has(key(r)) || r.roomsLeft >= wanted)
|
|
2271
|
+
continue;
|
|
2272
|
+
const seen = types.get(key(r));
|
|
2273
|
+
if (seen)
|
|
2274
|
+
seen.left = Math.max(seen.left, r.roomsLeft);
|
|
2275
|
+
else
|
|
2276
|
+
types.set(key(r), { room: r, left: r.roomsLeft });
|
|
2277
|
+
}
|
|
2278
|
+
return [...types.entries()].map(([id, { room: r, left }]) => ({
|
|
2279
|
+
id,
|
|
2280
|
+
name: r.roomType?.name ?? r.name,
|
|
2281
|
+
...((r.roomType?.names ?? r.names) ? { names: r.roomType?.names ?? r.names } : {}),
|
|
2282
|
+
sleeps: r.sleeps,
|
|
2283
|
+
...(r.maxChildren ? { maxChildren: r.maxChildren } : {}),
|
|
2284
|
+
...(r.sizeSqm ? { sizeSqm: r.sizeSqm } : {}),
|
|
2285
|
+
...(r.beds ? { beds: r.beds } : {}),
|
|
2286
|
+
...(r.bedTypes ? { bedTypes: r.bedTypes } : {}),
|
|
2287
|
+
...(r.view ? { view: r.view } : {}),
|
|
2288
|
+
...(r.window ? { window: r.window } : {}),
|
|
2289
|
+
...(r.floor ? { floor: r.floor } : {}),
|
|
2290
|
+
...(r.imageUrl ? { imageUrl: r.imageUrl } : {}),
|
|
2291
|
+
// Some left, but not as many as were asked for.
|
|
2292
|
+
...(left > 0 ? { left } : {}),
|
|
2293
|
+
}));
|
|
2294
|
+
};
|
|
2224
2295
|
const identity = (deps, ctx, key, args = {}) => {
|
|
2225
2296
|
const email = str(args.email);
|
|
2226
2297
|
const member = deps.members.read(key);
|
|
@@ -3329,6 +3400,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3329
3400
|
// with what is true of each (`facets`), so a chip switched on or off on the
|
|
3330
3401
|
// card needs no call to the server.
|
|
3331
3402
|
const terms = roomTermsOf(args);
|
|
3403
|
+
const soldOut = soldOutTypesOf(detail, enough, roomsWanted);
|
|
3332
3404
|
const rooms = enough.map((r) => ({
|
|
3333
3405
|
...r,
|
|
3334
3406
|
facets: facetsOf(r),
|
|
@@ -3366,6 +3438,8 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3366
3438
|
rooms_wanted: roomsWanted,
|
|
3367
3439
|
roomFilters: optionsOf(enough),
|
|
3368
3440
|
activeFilters: activeKeysOf(terms),
|
|
3441
|
+
// Types with no room to book for these nights, said and not left out.
|
|
3442
|
+
...(byTheHour || !soldOut.length ? {} : { soldOut }),
|
|
3369
3443
|
...flex.structured,
|
|
3370
3444
|
},
|
|
3371
3445
|
text: [
|
|
@@ -4018,6 +4092,17 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
4018
4092
|
: {}),
|
|
4019
4093
|
paid: false,
|
|
4020
4094
|
...(remembered ? { remembered: remembered.kept } : {}),
|
|
4095
|
+
// What they come to together, said by the server like every figure on
|
|
4096
|
+
// the card - never added up there (r10, #15). Only in one currency.
|
|
4097
|
+
...(several &&
|
|
4098
|
+
booked.every(({ booking }) => booking.quote.total.currency === first.booking.quote.total.currency)
|
|
4099
|
+
? {
|
|
4100
|
+
totalAll: formatMoney({
|
|
4101
|
+
minor: booked.reduce((n, { booking }) => n + booking.quote.total.minor, 0),
|
|
4102
|
+
currency: first.booking.quote.total.currency,
|
|
4103
|
+
}),
|
|
4104
|
+
}
|
|
4105
|
+
: {}),
|
|
4021
4106
|
holdUntil: first.booking.holdUntil,
|
|
4022
4107
|
total: formatMoney(first.booking.quote.total),
|
|
4023
4108
|
...(first.asked.length ? { requested: first.asked } : {}),
|