@curless/hotel-storefront 0.30.4 → 0.30.6
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/huazhu/backend.d.ts.map +1 -1
- package/dist/huazhu/backend.js +42 -12
- package/dist/huazhu/backend.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.js +2 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +5 -2
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.generated.js","sourceRoot":"","sources":["../src/card.generated.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,wEAAwE;AACxE,gFAAgF;AAChF,4DAA4D;AAC5D,MAAM,CAAC,MAAM,eAAe,GAAW,MAAM,CAAC,IAAI,CAChD,
|
|
1
|
+
{"version":3,"file":"card.generated.js","sourceRoot":"","sources":["../src/card.generated.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,wEAAwE;AACxE,gFAAgF;AAChF,4DAA4D;AAC5D,MAAM,CAAC,MAAM,eAAe,GAAW,MAAM,CAAC,IAAI,CAChD,s4siBAAs4siB,EACt4siB,QAAQ,CACT,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAEnB,6GAA6G;AAC7G,MAAM,CAAC,MAAM,qBAAqB,GAChC,kEAAkE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/huazhu/backend.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/huazhu/backend.ts"],"names":[],"mappings":"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"}
|
package/dist/huazhu/backend.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomBytes, randomUUID } from 'node:crypto';
|
|
2
|
-
import { DEFAULT_PAGE, MAX_PAGE, REQUEST_KINDS, REQUEST_NOTE_MAX, guestTooLong,
|
|
2
|
+
import { DEFAULT_PAGE, MAX_PAGE, REQUEST_KINDS, REQUEST_NOTE_MAX, guestTooLong, partyNeedsOf, } from '../backend.js';
|
|
3
3
|
import { addDays, arrivalInstant, atHotelTime, nights as nightsBetween, stayProblem, stayProblemOf, todayAt, } from '../dates.js';
|
|
4
4
|
import { byWords, splitByStay } from '../demo-hotels.js';
|
|
5
5
|
import { FACILITIES, hasFacility } from '../facilities.js';
|
|
@@ -511,6 +511,36 @@ export const createHuazhuHotels = (opts) => {
|
|
|
511
511
|
return got;
|
|
512
512
|
};
|
|
513
513
|
const productsOf = async (hotelId) => (await productsWithDays(hotelId)).value;
|
|
514
|
+
/**
|
|
515
|
+
* Whether a hotel sells rooms by the hour at all (`Hotel.sellsHourly`): any
|
|
516
|
+
* product checked in by the hour - not whether one is left today, which the
|
|
517
|
+
* hotel's page says with a reason. Only where this deployment sells them.
|
|
518
|
+
*
|
|
519
|
+
* ⚠️ A HOTEL THAT SELLS NONE SHOWED THE "BY THE HOUR" SWITCH, and every
|
|
520
|
+
* press of it led to "none here" (robin, 2026-10-14). Unknown is left out,
|
|
521
|
+
* and the card keeps the switch: hiding it from a hotel that does sell them
|
|
522
|
+
* is the worse mistake.
|
|
523
|
+
*/
|
|
524
|
+
const sellsHourlyOf = async (hotelId) => {
|
|
525
|
+
if (!opts.hourly)
|
|
526
|
+
return undefined;
|
|
527
|
+
try {
|
|
528
|
+
return (await productsOf(hotelId)).some((p) => p.checkinType === 'HOUR');
|
|
529
|
+
}
|
|
530
|
+
catch {
|
|
531
|
+
return undefined;
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
/** The same, only from a product list already read - a list asks Huazhu nothing more for it. */
|
|
535
|
+
const sellsHourlyKnown = (hotelId) => {
|
|
536
|
+
if (!opts.hourly)
|
|
537
|
+
return undefined;
|
|
538
|
+
const hit = productsCache.get(hotelId);
|
|
539
|
+
if (!hit || now() - hit.at >= productsTtl)
|
|
540
|
+
return undefined;
|
|
541
|
+
return hit.value.some((p) => p.checkinType === 'HOUR');
|
|
542
|
+
};
|
|
543
|
+
const withSells = (hotel, sells) => sells === undefined ? hotel : { ...hotel, sellsHourly: sells };
|
|
514
544
|
/** Whether a hotel sells any room by the hour on its today - from its products, no prices. */
|
|
515
545
|
const sellsByTheHourToday = async (hotelId) => (await productsOf(hotelId)).some((p) => p.checkinType === 'HOUR' && inStayWindow(p.stayWindow, today()));
|
|
516
546
|
const ariCache = new Map();
|
|
@@ -800,12 +830,6 @@ export const createHuazhuHotels = (opts) => {
|
|
|
800
830
|
...(maxChildren > 0 && maxChildren < 99 ? { maxChildren } : {}),
|
|
801
831
|
};
|
|
802
832
|
};
|
|
803
|
-
/** A party too big for any room here, said by partyNeeds with its numbers beside it. */
|
|
804
|
-
const partyWhy = (guests, largest) => ({
|
|
805
|
-
why: partyNeeds(guests, largest),
|
|
806
|
-
code: 'party',
|
|
807
|
-
...(largest > 0 ? { args: { largest, rooms: Math.ceil(guests / largest) } } : {}),
|
|
808
|
-
});
|
|
809
833
|
/** A hotel's "nothing to book", as HotelDetail carries it. */
|
|
810
834
|
const noRoomsOf = (w) => ({
|
|
811
835
|
noRooms: w.why,
|
|
@@ -827,7 +851,7 @@ export const createHuazhuHotels = (opts) => {
|
|
|
827
851
|
return { why: 'This hotel sells no rooms by the hour today.', code: 'hourly-none' };
|
|
828
852
|
const fails = priced.map((p) => p.res).filter((r) => !r.ok);
|
|
829
853
|
if (fails.length > 0 && fails.every((f) => f.kind === 'party'))
|
|
830
|
-
return
|
|
854
|
+
return partyNeedsOf(guests, largestOf(fails));
|
|
831
855
|
if (fails.some((f) => f.kind === 'prepaid'))
|
|
832
856
|
return {
|
|
833
857
|
why: "This hotel's rooms by the hour are paid in advance, and this connector books rates paid at the hotel.",
|
|
@@ -864,7 +888,7 @@ export const createHuazhuHotels = (opts) => {
|
|
|
864
888
|
const kinds = new Set(fails.map((f) => f.kind));
|
|
865
889
|
const only = (k) => kinds.size === 1 && kinds.has(k);
|
|
866
890
|
if (only('party'))
|
|
867
|
-
return
|
|
891
|
+
return partyNeedsOf(stay.guests, largestOf(fails));
|
|
868
892
|
if (only('prepaid'))
|
|
869
893
|
return {
|
|
870
894
|
why: 'Every rate here for those nights is paid in advance, and this connector books rates paid at the hotel.',
|
|
@@ -2207,7 +2231,11 @@ export const createHuazhuHotels = (opts) => {
|
|
|
2207
2231
|
// The page is priced whatever else was: it is what the guest sees.
|
|
2208
2232
|
if (stay && !priceEverything)
|
|
2209
2233
|
await pool(shown.map((m) => m.raw), PRICE_CONCURRENCY, priceHotel);
|
|
2210
|
-
const priced = (
|
|
2234
|
+
const priced = (listed) => {
|
|
2235
|
+
const m = {
|
|
2236
|
+
...listed,
|
|
2237
|
+
hotel: withSells(listed.hotel, sellsHourlyKnown(listed.raw.hotelId)),
|
|
2238
|
+
};
|
|
2211
2239
|
if (!stay)
|
|
2212
2240
|
return m.hotel;
|
|
2213
2241
|
const b = bestFor(m.raw, f);
|
|
@@ -2308,7 +2336,9 @@ export const createHuazhuHotels = (opts) => {
|
|
|
2308
2336
|
const raw = findHotel(id);
|
|
2309
2337
|
if (!raw)
|
|
2310
2338
|
return null;
|
|
2311
|
-
const detail = {
|
|
2339
|
+
const detail = {
|
|
2340
|
+
hotel: withSells(toHotel(raw, view, now()), await sellsHourlyOf(raw.hotelId)),
|
|
2341
|
+
};
|
|
2312
2342
|
if (!stay)
|
|
2313
2343
|
return detail;
|
|
2314
2344
|
const problem = stayProblemOf(stay, today());
|
|
@@ -2343,7 +2373,7 @@ export const createHuazhuHotels = (opts) => {
|
|
|
2343
2373
|
const raw = findHotel(id);
|
|
2344
2374
|
if (!raw)
|
|
2345
2375
|
return null;
|
|
2346
|
-
const hotel = toHotel(raw, view, now());
|
|
2376
|
+
const hotel = withSells(toHotel(raw, view, now()), await sellsHourlyOf(raw.hotelId));
|
|
2347
2377
|
const date = today();
|
|
2348
2378
|
const stay = { checkIn: date, checkOut: date, guests };
|
|
2349
2379
|
let priced;
|