@curless/hotel-storefront 0.23.1 → 0.24.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.
Files changed (93) hide show
  1. package/README.md +28 -11
  2. package/dist/__tests__/__fixtures__/huazhu-fake.d.ts +54 -0
  3. package/dist/__tests__/__fixtures__/huazhu-fake.d.ts.map +1 -0
  4. package/dist/__tests__/__fixtures__/huazhu-fake.js +340 -0
  5. package/dist/__tests__/__fixtures__/huazhu-fake.js.map +1 -0
  6. package/dist/__tests__/huazhu-backend.test.d.ts +2 -0
  7. package/dist/__tests__/huazhu-backend.test.d.ts.map +1 -0
  8. package/dist/__tests__/huazhu-backend.test.js +434 -0
  9. package/dist/__tests__/huazhu-backend.test.js.map +1 -0
  10. package/dist/__tests__/huazhu-cancel-policy.test.d.ts +2 -0
  11. package/dist/__tests__/huazhu-cancel-policy.test.d.ts.map +1 -0
  12. package/dist/__tests__/huazhu-cancel-policy.test.js +82 -0
  13. package/dist/__tests__/huazhu-cancel-policy.test.js.map +1 -0
  14. package/dist/__tests__/huazhu-sellable.test.d.ts +2 -0
  15. package/dist/__tests__/huazhu-sellable.test.d.ts.map +1 -0
  16. package/dist/__tests__/huazhu-sellable.test.js +192 -0
  17. package/dist/__tests__/huazhu-sellable.test.js.map +1 -0
  18. package/dist/__tests__/server.test.js +129 -4
  19. package/dist/__tests__/server.test.js.map +1 -1
  20. package/dist/__tests__/tool-descriptions.test.js +57 -4
  21. package/dist/__tests__/tool-descriptions.test.js.map +1 -1
  22. package/dist/__tests__/tools.test.js +2 -0
  23. package/dist/__tests__/tools.test.js.map +1 -1
  24. package/dist/backend.d.ts +27 -0
  25. package/dist/backend.d.ts.map +1 -1
  26. package/dist/backend.js +7 -0
  27. package/dist/backend.js.map +1 -1
  28. package/dist/card.generated.d.ts +1 -1
  29. package/dist/card.generated.js +2 -2
  30. package/dist/card.generated.js.map +1 -1
  31. package/dist/config.d.ts +52 -4
  32. package/dist/config.d.ts.map +1 -1
  33. package/dist/config.js.map +1 -1
  34. package/dist/facilities.d.ts.map +1 -1
  35. package/dist/facilities.js +7 -5
  36. package/dist/facilities.js.map +1 -1
  37. package/dist/huazhu/backend.d.ts +40 -0
  38. package/dist/huazhu/backend.d.ts.map +1 -0
  39. package/dist/huazhu/backend.js +1318 -0
  40. package/dist/huazhu/backend.js.map +1 -0
  41. package/dist/huazhu/bookings.d.ts +81 -0
  42. package/dist/huazhu/bookings.d.ts.map +1 -0
  43. package/dist/huazhu/bookings.js +189 -0
  44. package/dist/huazhu/bookings.js.map +1 -0
  45. package/dist/huazhu/cancel-policy.d.ts +69 -0
  46. package/dist/huazhu/cancel-policy.d.ts.map +1 -0
  47. package/dist/huazhu/cancel-policy.js +201 -0
  48. package/dist/huazhu/cancel-policy.js.map +1 -0
  49. package/dist/huazhu/catalog.d.ts +75 -0
  50. package/dist/huazhu/catalog.d.ts.map +1 -0
  51. package/dist/huazhu/catalog.js +251 -0
  52. package/dist/huazhu/catalog.js.map +1 -0
  53. package/dist/huazhu/check.d.ts +5 -0
  54. package/dist/huazhu/check.d.ts.map +1 -0
  55. package/dist/huazhu/check.js +170 -0
  56. package/dist/huazhu/check.js.map +1 -0
  57. package/dist/huazhu/client.d.ts +100 -0
  58. package/dist/huazhu/client.d.ts.map +1 -0
  59. package/dist/huazhu/client.js +232 -0
  60. package/dist/huazhu/client.js.map +1 -0
  61. package/dist/huazhu/sellable.d.ts +81 -0
  62. package/dist/huazhu/sellable.d.ts.map +1 -0
  63. package/dist/huazhu/sellable.js +219 -0
  64. package/dist/huazhu/sellable.js.map +1 -0
  65. package/dist/huazhu/wire.d.ts +389 -0
  66. package/dist/huazhu/wire.d.ts.map +1 -0
  67. package/dist/huazhu/wire.js +72 -0
  68. package/dist/huazhu/wire.js.map +1 -0
  69. package/dist/index.js +18 -4
  70. package/dist/index.js.map +1 -1
  71. package/dist/legal.d.ts +4 -3
  72. package/dist/legal.d.ts.map +1 -1
  73. package/dist/legal.js +33 -18
  74. package/dist/legal.js.map +1 -1
  75. package/dist/lib.d.ts +8 -3
  76. package/dist/lib.d.ts.map +1 -1
  77. package/dist/lib.js +8 -1
  78. package/dist/lib.js.map +1 -1
  79. package/dist/server.d.ts +20 -8
  80. package/dist/server.d.ts.map +1 -1
  81. package/dist/server.js +132 -28
  82. package/dist/server.js.map +1 -1
  83. package/dist/surface.d.ts +2 -1
  84. package/dist/surface.d.ts.map +1 -1
  85. package/dist/surface.js +37 -10
  86. package/dist/surface.js.map +1 -1
  87. package/dist/tools.d.ts +33 -20
  88. package/dist/tools.d.ts.map +1 -1
  89. package/dist/tools.js +130 -11
  90. package/dist/tools.js.map +1 -1
  91. package/dist/types.d.ts +21 -2
  92. package/dist/types.d.ts.map +1 -1
  93. package/package.json +1 -1
package/README.md CHANGED
@@ -19,7 +19,7 @@ until someone names the nights.** Everything that can carry a price takes a
19
19
  deliberately separate from the parts that can. A connector that guesses "this
20
20
  weekend" books someone the wrong nights, and they find out at the front desk.
21
21
 
22
- ## The eleven tools
22
+ ## The tools
23
23
 
24
24
  | | |
25
25
  |---|---|
@@ -27,7 +27,7 @@ weekend" books someone the wrong nights, and they find out at the front desk.
27
27
  | `get_<brand>_hotel` | One hotel; with `checkIn`/`checkOut`, its rooms priced for those nights |
28
28
  | `list_<brand>_extras` | Transfers, dining, experiences, spa, family |
29
29
  | `add_to_<brand>_trip` · `view_` · `clear_` | The trip: room nights plus add-ons, priced as one |
30
- | `request_<brand>_booking` | Holds the rooms, issues a confirmation code |
30
+ | `request_<brand>_booking` | Holds the rooms (demo) or books them, paid at the hotel (a group's own API); a confirmation code per stay |
31
31
  | `list_my_<brand>_bookings` | |
32
32
  | `preview_<brand>_cancellation` · `cancel_<brand>_booking` | The fee and its rule, before anything is cancelled |
33
33
  | `get_<brand>_hotel_policies` | What the property itself publishes |
@@ -41,19 +41,36 @@ attestations require.
41
41
  - **No dates, no line.** `add_to_*_trip` asks rather than guessing.
42
42
  - **Preview, then cancel.** `cancel_*_booking` returns the fee and its rule and
43
43
  cancels nothing until it is called again with `confirmed`.
44
- - **Held is not paid.** A booking request takes no money and collects no card;
45
- the answer says so, and the card says so in as many words.
44
+ - **Held is not paid, and booked is not paid.** A booking takes no money and
45
+ collects no card; the answer says so, and the card says so in as many words.
46
46
 
47
47
  ## Where the rooms come from
48
48
 
49
- Everything goes through one `HotelBackend` interface. The implementation shipped
50
- here reads a JSON file and prices it (`DemoHotels`); a group's own booking API
51
- arrives as a second implementation, and the tools, the card and the evals do not
52
- learn about it.
49
+ Everything goes through one `HotelBackend` interface, and there are two:
50
+
51
+ - **`data.source: "demo"`** reads a JSON file and prices it (`DemoHotels`).
52
+ Every price-bearing answer carries `demo: true` and says so in words — an
53
+ invented rate presented as bookable is the one failure a booking connector
54
+ cannot have.
55
+ - **`data.source: "api"`, `data.api.provider: "huazhu"`** books for real
56
+ through Huazhu's distributor OpenAPI: the hotel list kept on disk and
57
+ current, prices, rules and rooms left asked for live, `prebook` before every
58
+ booking, one reservation per stay paid at the hotel, and a booking whose
59
+ answer was lost followed up by the consistency query for the eight minutes
60
+ Huazhu's rules require. Credentials come from the environment
61
+ (`HUAZHU_CLIENT_ID`, `HUAZHU_CLIENT_SECRET`, `HUAZHU_DISTRIBUTOR_ID`), never
62
+ the config.
63
+
64
+ A backend says what it cannot do through `capabilities` — Huazhu has no loyalty
65
+ sign-in, no add-ons and no in-place date change — and the tools, the server
66
+ instructions, the card and the legal pages leave those out rather than offering
67
+ something that always says no.
53
68
 
54
- While the data is a demonstration file, every price-bearing answer carries
55
- `demo: true` and says so in words — an invented rate presented as bookable is
56
- the one failure a booking connector cannot have.
69
+ ```bash
70
+ # The first call against a real environment, read-only - it never books:
71
+ HUAZHU_CLIENT_ID=… HUAZHU_CLIENT_SECRET=… HUAZHU_DISTRIBUTOR_ID=… \
72
+ npx curless-hotel-storefront --check ./config.json
73
+ ```
57
74
 
58
75
  ## Payment
59
76
 
@@ -0,0 +1,54 @@
1
+ import type { BookRequest, DailyOffer, HotelStatic, OrderStatus, Product } from '../../huazhu/wire.js';
2
+ export type FakeRate = {
3
+ product: Product;
4
+ /** Taxes in, per room-night, for up to `adults` adults. */
5
+ price: (date: string) => number;
6
+ before?: (date: string) => number;
7
+ adults?: number;
8
+ inventory?: (date: string) => number;
9
+ guarantee?: string;
10
+ cancel?: string;
11
+ meal?: {
12
+ type: string;
13
+ count: number;
14
+ };
15
+ restriction?: Partial<Record<keyof DailyOffer['restriction'], (date: string) => unknown>>;
16
+ };
17
+ /** A failure injected on `path`: after `skip` good calls, `times` times (default once). */
18
+ type Fail = {
19
+ path: string;
20
+ kind: 'unreachable' | 'http502' | 'answer-lost' | number;
21
+ times?: number;
22
+ skip?: number;
23
+ };
24
+ export type FakeBooking = {
25
+ resId: string;
26
+ distributorResId: string;
27
+ request: BookRequest;
28
+ status: OrderStatus;
29
+ cancelCode: string;
30
+ };
31
+ export declare const createFakeHuazhu: (opts: {
32
+ hotels: HotelStatic[];
33
+ rates: Record<string, FakeRate[]>;
34
+ now: () => number;
35
+ distributorId?: string;
36
+ clientId?: string;
37
+ secret?: string;
38
+ }) => {
39
+ fetch: typeof fetch;
40
+ calls: {
41
+ path: string;
42
+ body: unknown;
43
+ headers: Record<string, string>;
44
+ }[];
45
+ bookings: Map<string, FakeBooking>;
46
+ fail: (f: Fail) => number;
47
+ retireToken: () => void;
48
+ readonly tokens: number;
49
+ };
50
+ /** One domestic hotel shaped like the documentation's example. */
51
+ export declare const fakeHotel: (id: string, over?: Partial<HotelStatic>) => HotelStatic;
52
+ export declare const product: (roomTypeCode: string, rateCode: string, over?: Partial<Product>) => Product;
53
+ export {};
54
+ //# sourceMappingURL=huazhu-fake.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"huazhu-fake.d.ts","sourceRoot":"","sources":["../../../src/__tests__/__fixtures__/huazhu-fake.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACX,WAAW,EAEX,OAAO,EACR,MAAM,sBAAsB,CAAC;AAW9B,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,2DAA2D;IAC3D,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC;CAC3F,CAAC;AAEF,2FAA2F;AAC3F,KAAK,IAAI,GAAG;IACV,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,WAAW,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,MAAM;IACrC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClC,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;WA6SW,OAAO,KAAK;;cAtSD,MAAM;cAAQ,OAAO;iBAAW,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;;;cAyS/D,IAAI;;;CAQjB,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,SAAS,GAAI,IAAI,MAAM,EAAE,OAAM,OAAO,CAAC,WAAW,CAAM,KAAG,WAwDtE,CAAC;AAEH,eAAO,MAAM,OAAO,GAClB,cAAc,MAAM,EACpB,UAAU,MAAM,EAChB,OAAM,OAAO,CAAC,OAAO,CAAM,KAC1B,OAQD,CAAC"}
@@ -0,0 +1,340 @@
1
+ import { addDays, nights } from '../../dates.js';
2
+ export const createFakeHuazhu = (opts) => {
3
+ const distributorId = opts.distributorId ?? 'CURLESS';
4
+ const basic = Buffer.from(`${opts.clientId ?? 'cid'}:${opts.secret ?? 'sec'}`).toString('base64');
5
+ let token = '';
6
+ let tokens = 0;
7
+ const fails = [];
8
+ const bookings = new Map();
9
+ const calls = [];
10
+ const held = new Map();
11
+ let resSeq = 1000;
12
+ const envelope = (code, content, message = code === 1000 ? 'Success' : 'Error', responseDes = '') => new Response(JSON.stringify({ code, ...(content !== undefined ? { content } : {}), message, responseDes }), {
13
+ status: 200,
14
+ headers: { 'content-type': 'application/json' },
15
+ });
16
+ const today = () => new Date(opts.now() + 8 * 3_600_000).toISOString().slice(0, 10);
17
+ const dates = (start, end) => {
18
+ const out = [];
19
+ for (let d = start; d <= end; d = addDays(d, 1))
20
+ out.push(d);
21
+ return out;
22
+ };
23
+ const key = (hotelId, p) => `${hotelId}|${p.roomTypeCode}|${p.rateCode}`;
24
+ const left = (hotelId, r, d) => Math.max(0, (r.inventory?.(d) ?? 5) - (held.get(`${key(hotelId, r.product)}|${d}`) ?? 0));
25
+ const offerOf = (hotelId, r, days) => {
26
+ const restriction = {
27
+ close: days.map((d) => r.restriction?.close?.(d) ?? false),
28
+ minStayArrival: days.map((d) => r.restriction?.minStayArrival?.(d) ?? null),
29
+ maxStayArrival: days.map((d) => r.restriction?.maxStayArrival?.(d) ?? 999),
30
+ minStayThrough: days.map((d) => r.restriction?.minStayThrough?.(d) ?? 0),
31
+ maxStayThrough: days.map((d) => r.restriction?.maxStayThrough?.(d) ?? 0),
32
+ minAdvanceDay: days.map((d) => r.restriction?.minAdvanceDay?.(d) ?? null),
33
+ maxAdvanceDay: days.map((d) => r.restriction?.maxAdvanceDay?.(d) ?? 999),
34
+ cta: days.map((d) => r.restriction?.cta?.(d) ?? false),
35
+ ctd: days.map((d) => r.restriction?.ctd?.(d) ?? false),
36
+ fplos: days.map((d) => r.restriction?.fplos?.(d) ?? null),
37
+ };
38
+ void hotelId;
39
+ return {
40
+ roomTypeCode: r.product.roomTypeCode,
41
+ rateCode: r.product.rateCode,
42
+ currencyCode: 'CNY',
43
+ rates: [
44
+ {
45
+ maxAdultCount: r.adults ?? 2,
46
+ amountAfterTax: days.map((d) => r.price(d)),
47
+ ...(r.before ? { amountBeforeTax: days.map((d) => r.before?.(d) ?? 0) } : {}),
48
+ },
49
+ ],
50
+ mealPlanType: r.meal?.type ?? 'RO',
51
+ mealPlanCounts: days.map(() => r.meal?.count ?? 0),
52
+ restriction,
53
+ guaranteePolicies: days.map(() => ({ code: r.guarantee ?? 'PL' })),
54
+ cancelPolicies: days.map(() => ({ code: r.cancel ?? '6PM1D1N_100P' })),
55
+ };
56
+ };
57
+ const handle = async (url, init) => {
58
+ const path = url.pathname;
59
+ const headers = Object.fromEntries(new Headers(init.headers).entries());
60
+ const body = init.body ? JSON.parse(String(init.body)) : undefined;
61
+ calls.push({ path, body, headers });
62
+ const f = fails.find((x) => x.path === path);
63
+ let passedOver = false;
64
+ if (f && (f.skip ?? 0) > 0) {
65
+ f.skip = (f.skip ?? 0) - 1;
66
+ passedOver = true;
67
+ }
68
+ else if (f && f.kind !== 'answer-lost') {
69
+ f.times = (f.times ?? 1) - 1;
70
+ if (f.times <= 0)
71
+ fails.splice(fails.indexOf(f), 1);
72
+ if (f.kind === 'unreachable')
73
+ throw new TypeError('fetch failed: ECONNRESET');
74
+ if (f.kind === 'http502')
75
+ return new Response('bad gateway', { status: 502 });
76
+ return envelope(f.kind, undefined, 'Injected', 'injected by the test');
77
+ }
78
+ if (path === '/oauth/token') {
79
+ if (headers.authorization !== `Basic ${basic}`)
80
+ return new Response('{"error":"invalid_client"}', { status: 401 });
81
+ tokens += 1;
82
+ token = `tok-${tokens}`;
83
+ return new Response(JSON.stringify({
84
+ access_token: token,
85
+ token_type: 'Bearer',
86
+ expires_in: 3600,
87
+ scope: 'ALL',
88
+ }), { status: 200 });
89
+ }
90
+ // Every business call: the four headers, and the current token.
91
+ if (headers.distributorid !== distributorId)
92
+ return envelope(2003, undefined, 'Invalid distributor ID');
93
+ if (!headers.timestamp || !headers.traceid)
94
+ return envelope(2004, undefined, 'Required field missing', 'timestamp/traceId');
95
+ if (headers.authorization !== `Bearer ${token}`)
96
+ return envelope(2002, undefined, 'Invalid token');
97
+ const hotel = (id) => opts.hotels.find((h) => h.hotelId === id);
98
+ switch (path) {
99
+ case '/hotels':
100
+ return envelope(1000, opts.hotels.map((h) => ({ hotelId: h.hotelId, hotelName: h.hotelName })));
101
+ case '/hotel': {
102
+ const h = hotel(body.hotelId);
103
+ return h ? envelope(1000, h) : envelope(3201, undefined, 'Invalid hotel Id');
104
+ }
105
+ case '/ari/products': {
106
+ if (!hotel(body.hotelId))
107
+ return envelope(4101, undefined, 'Invalid hotel Id');
108
+ return envelope(1000, {
109
+ hotelId: body.hotelId,
110
+ sellDays: 90,
111
+ products: (opts.rates[body.hotelId] ?? []).map((r) => r.product),
112
+ });
113
+ }
114
+ case '/ari/daily/offers':
115
+ case '/ari/daily/inventory': {
116
+ if (!hotel(body.hotelId))
117
+ return envelope(path.endsWith('offers') ? 4201 : 4304, undefined, 'Invalid hotel Id');
118
+ if (!body.checkinType)
119
+ return envelope(2004, undefined, 'Required field missing', 'checkinType');
120
+ if (nights(body.startDate, body.endDate) > 29 || body.endDate < body.startDate)
121
+ return envelope(path.endsWith('offers') ? 4203 : 4301, undefined, 'Start date and end date does not match the rules');
122
+ if (body.startDate < addDays(today(), -1))
123
+ return envelope(path.endsWith('offers') ? 4205 : 4303, undefined, 'Start date is invalid');
124
+ const days = dates(body.startDate, body.endDate);
125
+ const rates = opts.rates[body.hotelId] ?? [];
126
+ if (path.endsWith('offers')) {
127
+ return envelope(1000, {
128
+ hotelId: body.hotelId,
129
+ startDate: body.startDate,
130
+ endDate: body.endDate,
131
+ dailyOffers: rates.map((r) => offerOf(body.hotelId, r, days)),
132
+ });
133
+ }
134
+ return envelope(1000, {
135
+ hotelId: body.hotelId,
136
+ startDate: body.startDate,
137
+ endDate: body.endDate,
138
+ dailyInventories: rates.map((r) => ({
139
+ roomTypeCode: r.product.roomTypeCode,
140
+ rateCode: r.product.rateCode,
141
+ inventories: days.map((d) => left(body.hotelId, r, d)),
142
+ })),
143
+ });
144
+ }
145
+ case '/reservation/prebook':
146
+ case '/reservation/book': {
147
+ const req = body;
148
+ const booking = path.endsWith('book') && !path.endsWith('prebook');
149
+ if (booking) {
150
+ if (!req.distributorResId)
151
+ return envelope(2004, undefined, 'Required field missing', 'distributorResId');
152
+ const had = [...bookings.values()].find((b) => b.distributorResId === req.distributorResId);
153
+ if (had)
154
+ return envelope(5218, undefined, 'DistributorResId already exist');
155
+ if (!req.contactPerson?.lastName || req.contactPerson.lastName.length > 16)
156
+ return envelope(2005, undefined, 'Invalid field', 'contactPerson.lastName');
157
+ }
158
+ const line = req.reservations?.[0];
159
+ if (!line)
160
+ return envelope(2004, undefined, 'Required field missing', 'reservations');
161
+ const r = (opts.rates[req.hotelId] ?? []).find((x) => x.product.roomTypeCode === line.roomTypeCode && x.product.rateCode === line.rateCode);
162
+ if (!r)
163
+ return envelope(booking ? 5236 : 5123, undefined, 'No match found');
164
+ const nightsOf = dates(line.checkin, addDays(line.checkout, -1));
165
+ const want = nightsOf.map((d) => r.price(d));
166
+ const priceOk = want.length === line.amountAfterTax.length &&
167
+ want.every((x, i) => x === line.amountAfterTax[i]);
168
+ const ari = {
169
+ checkin: line.checkin,
170
+ checkout: line.checkout,
171
+ ...offerOf(req.hotelId, r, nightsOf),
172
+ inventories: nightsOf.map((d) => left(req.hotelId, r, d)),
173
+ };
174
+ if (!priceOk)
175
+ return envelope(booking ? 5209 : 5108, { hotelId: req.hotelId, reservationsAri: [ari] }, 'Price incorrect for room');
176
+ if (nightsOf.some((d) => left(req.hotelId, r, d) < line.roomCount))
177
+ return envelope(booking ? 5210 : 5109, { hotelId: req.hotelId, reservationsAri: [ari] }, 'No rooms available for requested dates');
178
+ const guarantee = r.guarantee ?? 'PL';
179
+ const allowed = {
180
+ PL: ['NGPL', 'OGPL', 'CCPL'],
181
+ GTX: ['OGPL', 'OPN', 'CCPL', 'CPN'],
182
+ PN: ['OPN', 'CCPN', 'CPN'],
183
+ };
184
+ if (!(allowed[guarantee] ?? []).includes(req.paymentType))
185
+ return envelope(booking ? 5211 : 5114, undefined, 'Payment type invalid');
186
+ if (!booking)
187
+ return envelope(1000, {
188
+ hotelId: req.hotelId,
189
+ preBookToken: `PB${calls.length}`,
190
+ reservationsAri: [ari],
191
+ });
192
+ resSeq += 1;
193
+ const resId = `R${req.hotelId}${resSeq}`;
194
+ for (const d of nightsOf) {
195
+ const k = `${key(req.hotelId, r.product)}|${d}`;
196
+ held.set(k, (held.get(k) ?? 0) + line.roomCount);
197
+ }
198
+ bookings.set(resId, {
199
+ resId,
200
+ distributorResId: req.distributorResId,
201
+ request: req,
202
+ status: 'HOTEL_RESERVATION',
203
+ cancelCode: r.cancel ?? '6PM1D1N_100P',
204
+ });
205
+ const lost = passedOver
206
+ ? undefined
207
+ : fails.find((x) => x.path === path && x.kind === 'answer-lost');
208
+ if (lost) {
209
+ fails.splice(fails.indexOf(lost), 1);
210
+ throw new TypeError('fetch failed: read timeout');
211
+ }
212
+ return envelope(1000, { resId, resCode: `RC${resSeq}` });
213
+ }
214
+ case '/reservation/detail': {
215
+ const b = bookings.get(body.resId);
216
+ if (!b)
217
+ return envelope(5302, undefined, 'Reservation not found');
218
+ const line = b.request.reservations[0];
219
+ return envelope(1000, {
220
+ hotelId: b.request.hotelId,
221
+ checkInType: 'DAY',
222
+ paymentType: b.request.paymentType,
223
+ distributorResId: b.distributorResId,
224
+ resId: b.resId,
225
+ status: b.status,
226
+ bookingTime: opts.now(),
227
+ reservations: [
228
+ {
229
+ ...line,
230
+ cancelPolicyCode: b.cancelCode,
231
+ estimatedArrivalTime: line.estimatedArrivalTime ?? '12:00',
232
+ },
233
+ ],
234
+ });
235
+ }
236
+ case '/reservation/cancel': {
237
+ const b = bookings.get(body.resId);
238
+ if (!b)
239
+ return envelope(5403, undefined, 'Reservation not found');
240
+ if (b.status === 'HOTEL_CANCEL')
241
+ return envelope(5402, undefined, 'Reservation already cancelled');
242
+ b.status = 'HOTEL_CANCEL';
243
+ const line = b.request.reservations[0];
244
+ for (const d of dates(line.checkin, addDays(line.checkout, -1))) {
245
+ const k = `${b.request.hotelId}|${line.roomTypeCode}|${line.rateCode}|${d}`;
246
+ held.set(k, Math.max(0, (held.get(k) ?? 0) - line.roomCount));
247
+ }
248
+ return envelope(1000, { penaltyAmount: 0, penaltyCurrencyCode: 'CNY' });
249
+ }
250
+ case '/reservation/consistency/query': {
251
+ const b = [...bookings.values()].find((x) => x.distributorResId === body.distributorResId);
252
+ return b
253
+ ? envelope(1000, { resId: b.resId, status: b.status })
254
+ : envelope(5602, undefined, 'Reservation not found');
255
+ }
256
+ default:
257
+ return new Response('not found', { status: 404 });
258
+ }
259
+ };
260
+ return {
261
+ fetch: (async (input, init) => handle(new URL(typeof input === 'string' ? input : input instanceof URL ? input.href : input.url), init ?? {})),
262
+ calls,
263
+ bookings,
264
+ fail: (f) => fails.push(f),
265
+ retireToken: () => {
266
+ token = `retired-${token}`;
267
+ },
268
+ get tokens() {
269
+ return tokens;
270
+ },
271
+ };
272
+ };
273
+ /** One domestic hotel shaped like the documentation's example. */
274
+ export const fakeHotel = (id, over = {}) => ({
275
+ hotelId: id,
276
+ hotelName: `汉庭酒店(上海人民广场${id}店)`,
277
+ hotelNameEn: `Hanting Hotel Shanghai People's Square ${id}`,
278
+ brandCode: 2,
279
+ brandName: '汉庭',
280
+ provinceNo: '310000',
281
+ provinceName: '上海市',
282
+ cityNo: '310100',
283
+ cityName: '上海市',
284
+ countyNo: '310101',
285
+ countyName: '黄浦区',
286
+ hotelAddress: '上海市黄浦区延安东路1号',
287
+ hotelAddressEn: "1 Yan'an East Road, Huangpu District, Shanghai",
288
+ telephone: '63200000',
289
+ hotelWordIntroduce: '近人民广场地铁站,步行可达南京路步行街。',
290
+ international: false,
291
+ tradeCurrency: 'CNY',
292
+ hotelRoomTypeList: [
293
+ {
294
+ roomTypeCode: 'DR1',
295
+ roomTypeName: '高级大床房',
296
+ hotelArea: 20,
297
+ isHasWindow: '1',
298
+ maxOccupancy: 999,
299
+ status: 1,
300
+ bedTypeList: [{ bedTypeCode: 'A', bedSpecNo: '-1', bedTypeName: '大床', bedSpec: '1.8m' }],
301
+ },
302
+ {
303
+ roomTypeCode: 'TR1',
304
+ roomTypeName: '高级双床房',
305
+ hotelArea: 22,
306
+ isHasWindow: '3',
307
+ maxOccupancy: 2,
308
+ status: 1,
309
+ bedTypeList: [{ bedTypeCode: 'B', bedSpecNo: '-1', bedTypeName: '双床', bedSpec: '1.2m' }],
310
+ },
311
+ ],
312
+ hotelServiceList: [
313
+ { childClassCode: 71, childClassName: '健身房' },
314
+ { childClassCode: 49, childClassName: '中餐厅' },
315
+ ],
316
+ hotelPhotoList: [
317
+ { typeCode: 'ImagePhoto', fileUrl: 'http://ws-p.example.com/f/a.jpg', sortId: 20, status: 1 },
318
+ {
319
+ typeCode: 'RoomType',
320
+ typeMappingCode: 'DR1',
321
+ fileUrl: 'http://ws-p.example.com/f/dr1.jpg',
322
+ sortId: 10,
323
+ status: 1,
324
+ },
325
+ ],
326
+ hotelTrafficList: [
327
+ { destinationType: '9', destinationName: '人民广场', destinationDistance: '300m' },
328
+ ],
329
+ ...over,
330
+ });
331
+ export const product = (roomTypeCode, rateCode, over = {}) => ({
332
+ roomTypeCode,
333
+ roomTypeName: roomTypeCode === 'DR1' ? '高级大床房' : '高级双床房',
334
+ rateCode,
335
+ rateCodeName: rateCode,
336
+ checkinType: 'DAY',
337
+ promotion: false,
338
+ ...over,
339
+ });
340
+ //# sourceMappingURL=huazhu-fake.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"huazhu-fake.js","sourceRoot":"","sources":["../../../src/__tests__/__fixtures__/huazhu-fake.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=huazhu-backend.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"huazhu-backend.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/huazhu-backend.test.ts"],"names":[],"mappings":""}