@curless/hotel-storefront 0.23.2 → 0.24.1

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 (107) hide show
  1. package/README.md +35 -11
  2. package/dist/__tests__/__fixtures__/huazhu-fake.d.ts +2 -0
  3. package/dist/__tests__/__fixtures__/huazhu-fake.d.ts.map +1 -0
  4. package/dist/__tests__/__fixtures__/huazhu-fake.js +3 -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-sandbox.test.d.ts +2 -0
  15. package/dist/__tests__/huazhu-sandbox.test.d.ts.map +1 -0
  16. package/dist/__tests__/huazhu-sandbox.test.js +172 -0
  17. package/dist/__tests__/huazhu-sandbox.test.js.map +1 -0
  18. package/dist/__tests__/huazhu-sellable.test.d.ts +2 -0
  19. package/dist/__tests__/huazhu-sellable.test.d.ts.map +1 -0
  20. package/dist/__tests__/huazhu-sellable.test.js +192 -0
  21. package/dist/__tests__/huazhu-sellable.test.js.map +1 -0
  22. package/dist/__tests__/server.test.js +129 -4
  23. package/dist/__tests__/server.test.js.map +1 -1
  24. package/dist/__tests__/tool-descriptions.test.js +85 -7
  25. package/dist/__tests__/tool-descriptions.test.js.map +1 -1
  26. package/dist/backend.d.ts +27 -0
  27. package/dist/backend.d.ts.map +1 -1
  28. package/dist/backend.js +7 -0
  29. package/dist/backend.js.map +1 -1
  30. package/dist/card.generated.d.ts +1 -1
  31. package/dist/card.generated.js +2 -2
  32. package/dist/card.generated.js.map +1 -1
  33. package/dist/config.d.ts +64 -4
  34. package/dist/config.d.ts.map +1 -1
  35. package/dist/config.js.map +1 -1
  36. package/dist/facilities.d.ts.map +1 -1
  37. package/dist/facilities.js +7 -5
  38. package/dist/facilities.js.map +1 -1
  39. package/dist/huazhu/backend.d.ts +40 -0
  40. package/dist/huazhu/backend.d.ts.map +1 -0
  41. package/dist/huazhu/backend.js +1318 -0
  42. package/dist/huazhu/backend.js.map +1 -0
  43. package/dist/huazhu/bookings.d.ts +81 -0
  44. package/dist/huazhu/bookings.d.ts.map +1 -0
  45. package/dist/huazhu/bookings.js +189 -0
  46. package/dist/huazhu/bookings.js.map +1 -0
  47. package/dist/huazhu/cancel-policy.d.ts +69 -0
  48. package/dist/huazhu/cancel-policy.d.ts.map +1 -0
  49. package/dist/huazhu/cancel-policy.js +201 -0
  50. package/dist/huazhu/cancel-policy.js.map +1 -0
  51. package/dist/huazhu/catalog.d.ts +75 -0
  52. package/dist/huazhu/catalog.d.ts.map +1 -0
  53. package/dist/huazhu/catalog.js +251 -0
  54. package/dist/huazhu/catalog.js.map +1 -0
  55. package/dist/huazhu/check.d.ts +5 -0
  56. package/dist/huazhu/check.d.ts.map +1 -0
  57. package/dist/huazhu/check.js +170 -0
  58. package/dist/huazhu/check.js.map +1 -0
  59. package/dist/huazhu/client.d.ts +100 -0
  60. package/dist/huazhu/client.d.ts.map +1 -0
  61. package/dist/huazhu/client.js +232 -0
  62. package/dist/huazhu/client.js.map +1 -0
  63. package/dist/huazhu/fake.d.ts +64 -0
  64. package/dist/huazhu/fake.d.ts.map +1 -0
  65. package/dist/huazhu/fake.js +365 -0
  66. package/dist/huazhu/fake.js.map +1 -0
  67. package/dist/huazhu/sandbox.d.ts +26 -0
  68. package/dist/huazhu/sandbox.d.ts.map +1 -0
  69. package/dist/huazhu/sandbox.js +289 -0
  70. package/dist/huazhu/sandbox.js.map +1 -0
  71. package/dist/huazhu/sellable.d.ts +81 -0
  72. package/dist/huazhu/sellable.d.ts.map +1 -0
  73. package/dist/huazhu/sellable.js +219 -0
  74. package/dist/huazhu/sellable.js.map +1 -0
  75. package/dist/huazhu/wire.d.ts +389 -0
  76. package/dist/huazhu/wire.d.ts.map +1 -0
  77. package/dist/huazhu/wire.js +72 -0
  78. package/dist/huazhu/wire.js.map +1 -0
  79. package/dist/index.js +18 -4
  80. package/dist/index.js.map +1 -1
  81. package/dist/legal.d.ts +4 -3
  82. package/dist/legal.d.ts.map +1 -1
  83. package/dist/legal.js +71 -30
  84. package/dist/legal.js.map +1 -1
  85. package/dist/lib.d.ts +8 -3
  86. package/dist/lib.d.ts.map +1 -1
  87. package/dist/lib.js +8 -1
  88. package/dist/lib.js.map +1 -1
  89. package/dist/server.d.ts +20 -8
  90. package/dist/server.d.ts.map +1 -1
  91. package/dist/server.js +132 -28
  92. package/dist/server.js.map +1 -1
  93. package/dist/surface.d.ts +2 -1
  94. package/dist/surface.d.ts.map +1 -1
  95. package/dist/surface.js +42 -10
  96. package/dist/surface.js.map +1 -1
  97. package/dist/tools.d.ts +33 -20
  98. package/dist/tools.d.ts.map +1 -1
  99. package/dist/tools.js +122 -11
  100. package/dist/tools.js.map +1 -1
  101. package/dist/types.d.ts +21 -2
  102. package/dist/types.d.ts.map +1 -1
  103. package/dist/vocab.d.ts +5 -0
  104. package/dist/vocab.d.ts.map +1 -1
  105. package/dist/vocab.js +2 -1
  106. package/dist/vocab.js.map +1 -1
  107. 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,43 @@ 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
+ - **`data.api.sandbox: true`** is the same connector against a SIMULATED
64
+ Huazhu, for testing before there is an account: `node dist/huazhu/sandbox.js`
65
+ serves the distributor API as its documentation describes it, with eight
66
+ invented hotels named 【模拟】/[Sandbox] and no photographs, and keeps its
67
+ bookings in `SANDBOX_STATE_FILE`. The flag makes every answer say `demo`, the
68
+ instructions and the legal pages say it is a test environment, and nothing
69
+ claim a booking went to Huazhu - without it an api source is taken to be real.
70
+
71
+ A backend says what it cannot do through `capabilities` — Huazhu has no loyalty
72
+ sign-in, no add-ons and no in-place date change — and the tools, the server
73
+ instructions, the card and the legal pages leave those out rather than offering
74
+ something that always says no.
53
75
 
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.
76
+ ```bash
77
+ # The first call against a real environment, read-only - it never books:
78
+ HUAZHU_CLIENT_ID=… HUAZHU_CLIENT_SECRET=… HUAZHU_DISTRIBUTOR_ID=… \
79
+ npx curless-hotel-storefront --check ./config.json
80
+ ```
57
81
 
58
82
  ## Payment
59
83
 
@@ -0,0 +1,2 @@
1
+ export * from '../../huazhu/fake.js';
2
+ //# 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,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,3 @@
1
+ // The fake moved beside the code it stands in for, so the sandbox can serve it.
2
+ export * from '../../huazhu/fake.js';
3
+ //# 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":"AAAA,gFAAgF;AAChF,cAAc,sBAAsB,CAAC"}
@@ -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":""}
@@ -0,0 +1,434 @@
1
+ import { mkdtempSync, readFileSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { describe, expect, it } from 'vitest';
5
+ import { createHuazhuHotels } from '../huazhu/backend.js';
6
+ import { BookingStore, PENDING_WINDOW_MS, Reconciler } from '../huazhu/bookings.js';
7
+ import { Catalog } from '../huazhu/catalog.js';
8
+ import { HuazhuClient, HuazhuRefusal, HuazhuUnreachable } from '../huazhu/client.js';
9
+ import { createFakeHuazhu, fakeHotel, product } from './__fixtures__/huazhu-fake.js';
10
+ // The Huazhu backend driven end to end against a fake of Huazhu's API built
11
+ // from its documentation: the catalog, search, a priced hotel, the date strip,
12
+ // and the booking flow with every way a real booking call can go wrong.
13
+ // 10:00 in Shanghai on 1 October 2026.
14
+ const T0 = Date.parse('2026-10-01T02:00:00Z');
15
+ const STAY = { checkIn: '2026-10-10', checkOut: '2026-10-12', guests: 2 };
16
+ const beijing = fakeHotel('2002', {
17
+ hotelName: '全季酒店(北京国贸店)',
18
+ hotelNameEn: 'JI Hotel Beijing Guomao',
19
+ brandName: '全季',
20
+ provinceName: '北京市',
21
+ cityName: '北京市',
22
+ cityNo: '110100',
23
+ countyName: '朝阳区',
24
+ hotelAddressEn: '1 Jianguo Road, Chaoyang District, Beijing',
25
+ hotelServiceList: [{ childClassCode: 73, childClassName: '游泳池' }],
26
+ hotelTrafficList: [{ destinationName: '国贸' }],
27
+ });
28
+ const setup = (opts = {}) => {
29
+ let t = T0;
30
+ const now = () => t;
31
+ const dir = opts.dir ?? mkdtempSync(join(tmpdir(), 'huazhu-'));
32
+ const rates = opts.rates ?? {
33
+ '1001': [
34
+ {
35
+ product: product('DR1', 'BAR', { rateCodeName: '门市价含早' }),
36
+ price: (d) => (d === '2026-10-11' ? 358 : 328),
37
+ before: (d) => (d === '2026-10-11' ? 338 : 309),
38
+ meal: { type: 'BB', count: 1 },
39
+ cancel: '6PM1D1N_100P',
40
+ },
41
+ { product: product('TR1', 'PREPAID'), price: () => 280, guarantee: 'PN' },
42
+ ],
43
+ '2002': [{ product: product('DR1', 'BAR2'), price: () => 420, cancel: 'AD0_0' }],
44
+ };
45
+ const fake = createFakeHuazhu({
46
+ hotels: opts.hotels ?? [fakeHotel('1001'), beijing],
47
+ rates,
48
+ now,
49
+ });
50
+ const client = new HuazhuClient({
51
+ baseUrl: 'https://biz.huazhu.test',
52
+ authUrl: 'https://auth.huazhu.test',
53
+ credentials: { clientId: 'cid', secret: 'sec', distributorId: 'CURLESS' },
54
+ fetch: fake.fetch,
55
+ now,
56
+ });
57
+ const log = [];
58
+ const catalog = new Catalog({ client, stateDir: dir, now, log: (l) => log.push(l) });
59
+ const store = new BookingStore(dir, now);
60
+ const reconciler = new Reconciler(store, client, now, (l) => log.push(l));
61
+ const backend = createHuazhuHotels({
62
+ brand: 'Huazhu',
63
+ client,
64
+ catalog,
65
+ store,
66
+ reconciler,
67
+ paymentType: opts.paymentType ?? 'NGPL',
68
+ language: 'zh',
69
+ tz: 'Asia/Shanghai',
70
+ now,
71
+ sleep: async (ms) => {
72
+ t += ms;
73
+ },
74
+ });
75
+ return {
76
+ fake,
77
+ client,
78
+ catalog,
79
+ store,
80
+ reconciler,
81
+ backend,
82
+ dir,
83
+ log,
84
+ advance: (ms) => {
85
+ t += ms;
86
+ },
87
+ };
88
+ };
89
+ const who = { sessionId: 'conv-1' };
90
+ const room = (hotelId, roomId, stay = STAY, rooms = 1) => ({
91
+ kind: 'room',
92
+ hotelId,
93
+ roomId,
94
+ stay,
95
+ rooms,
96
+ });
97
+ const guest = { name: 'Wei Zhang', email: 'wei@example.com', phone: '13800000000' };
98
+ describe('Huazhu catalog', () => {
99
+ it('copies every listed hotel to disk and drops one the list no longer has', async () => {
100
+ const s = setup();
101
+ await s.catalog.sync();
102
+ expect(s.catalog.size).toBe(2);
103
+ expect(JSON.parse(readFileSync(join(s.dir, 'catalog.json'), 'utf8')).order).toEqual([
104
+ '1001',
105
+ '2002',
106
+ ]);
107
+ // "将已经终止合作下线的酒店剔除下线": a hotel off the list is off the connector.
108
+ const again = setup({ dir: s.dir, hotels: [fakeHotel('1001')] });
109
+ expect(again.catalog.size).toBe(2);
110
+ await again.catalog.sync();
111
+ expect(again.catalog.size).toBe(1);
112
+ expect(again.catalog.get('2002')).toBeUndefined();
113
+ });
114
+ it('stops at the daily limit and keeps what it has', async () => {
115
+ const s = setup();
116
+ s.fake.fail({ path: '/hotel', kind: 3204, skip: 1 });
117
+ await s.catalog.sync();
118
+ expect(s.catalog.size).toBe(1);
119
+ expect(s.catalog.state().stoppedBecause).toMatch(/daily limit/);
120
+ expect(s.catalog.stale()).toBe(true);
121
+ });
122
+ });
123
+ describe('Huazhu search and prices', () => {
124
+ it('finds a city in Chinese or as the English address spells it, and words anywhere in the record', async () => {
125
+ const s = setup();
126
+ await s.catalog.sync();
127
+ expect((await s.backend.searchHotels({ city: '上海' })).hotels.map((h) => h.id)).toEqual([
128
+ '1001',
129
+ ]);
130
+ expect((await s.backend.searchHotels({ city: '上海市' })).hotels.map((h) => h.id)).toEqual([
131
+ '1001',
132
+ ]);
133
+ expect((await s.backend.searchHotels({ city: 'Beijing' })).hotels.map((h) => h.id)).toEqual([
134
+ '2002',
135
+ ]);
136
+ expect((await s.backend.searchHotels({ query: '国贸' })).hotels.map((h) => h.id)).toEqual([
137
+ '2002',
138
+ ]);
139
+ expect((await s.backend.searchHotels({ filters: { facilities: ['pool'] } })).hotels.map((h) => h.id)).toEqual(['2002']);
140
+ });
141
+ it('says out loud which knobs it could not apply', async () => {
142
+ const s = setup();
143
+ await s.catalog.sync();
144
+ const noDates = await s.backend.searchHotels({ sort: 'price-low' });
145
+ expect(noDates.unapplied?.join(' ')).toMatch(/publishes no price without/);
146
+ const rating = await s.backend.searchHotels({ sort: 'rating' });
147
+ expect(rating.unapplied?.join(' ')).toMatch(/no guest ratings/);
148
+ });
149
+ it('prices every hotel for named nights, and a price order holds', async () => {
150
+ const s = setup();
151
+ await s.catalog.sync();
152
+ const r = await s.backend.searchHotels({ stay: STAY, sort: 'price-high' });
153
+ expect(r.hotels.map((h) => h.id)).toEqual(['2002', '1001']);
154
+ expect(r.hotels[1]?.forStay?.total).toEqual({ minor: 68_600, currency: 'CNY' });
155
+ expect(r.unapplied).toBeUndefined();
156
+ });
157
+ it('opens a hotel with its sellable rooms, the prepaid rate left out', async () => {
158
+ const s = setup();
159
+ await s.catalog.sync();
160
+ const d = await s.backend.getHotel('1001', STAY);
161
+ expect(d?.hotel.name).toBe('汉庭酒店(上海人民广场1001店)');
162
+ expect(d?.hotel.imageUrl).toBe('https://ws-p.example.com/f/a.jpg');
163
+ expect(d?.rooms).toHaveLength(1);
164
+ const r = d?.rooms?.[0];
165
+ expect(r).toMatchObject({
166
+ id: 'DR1~BAR',
167
+ name: '高级大床房 · 门市价含早',
168
+ breakfast: true,
169
+ view: 'Window',
170
+ sizeSqm: 20,
171
+ stayTotal: { minor: 68_600, currency: 'CNY' },
172
+ taxesAndFees: { minor: 3_900, currency: 'CNY' },
173
+ nights: 2,
174
+ refundable: true,
175
+ // 6PM1D1N: free until 18:00 the day before, Shanghai time.
176
+ freeCancellationUntil: '2026-10-09T10:00:00.000Z',
177
+ imageUrl: 'https://ws-p.example.com/f/dr1.jpg',
178
+ });
179
+ });
180
+ it('says why when every rate is prepaid', async () => {
181
+ const s = setup({
182
+ rates: { '1001': [{ product: product('DR1', 'PP'), price: () => 300, guarantee: 'PN' }] },
183
+ });
184
+ await s.catalog.sync();
185
+ const d = await s.backend.getHotel('1001', STAY);
186
+ expect(d?.rooms).toEqual([]);
187
+ expect(d?.noRooms).toMatch(/paid in advance/);
188
+ });
189
+ it('prices the dates either side from one ARI call', async () => {
190
+ const s = setup();
191
+ await s.catalog.sync();
192
+ const before = s.fake.calls.filter((c) => c.path === '/ari/daily/offers').length;
193
+ const opts = await s.backend.datesAround('1001', STAY, { rooms: 1, span: 3 });
194
+ expect(opts.map((o) => o.checkIn)).toEqual([
195
+ '2026-10-07',
196
+ '2026-10-08',
197
+ '2026-10-09',
198
+ '2026-10-10',
199
+ '2026-10-11',
200
+ '2026-10-12',
201
+ '2026-10-13',
202
+ ]);
203
+ expect(opts.find((o) => o.chosen)?.from).toEqual({ minor: 68_600, currency: 'CNY' });
204
+ expect(s.fake.calls.filter((c) => c.path === '/ari/daily/offers').length - before).toBe(1);
205
+ });
206
+ it('asks for a new token once when Huazhu retires the old one, and carries on', async () => {
207
+ const s = setup();
208
+ await s.catalog.sync();
209
+ s.fake.retireToken();
210
+ expect((await s.backend.getHotel('1001', STAY))?.rooms).toHaveLength(1);
211
+ expect(s.fake.tokens).toBe(2);
212
+ });
213
+ it('a 502 from Huazhu is "could not ask", not "no rooms"', async () => {
214
+ const s = setup();
215
+ await s.catalog.sync();
216
+ s.fake.fail({ path: '/ari/daily/offers', kind: 'http502' });
217
+ const d = await s.backend.getHotel('1001', STAY);
218
+ expect(d?.noRooms).toMatch(/could not be asked/);
219
+ });
220
+ });
221
+ describe('Huazhu bookings', () => {
222
+ it('checks with prebook, then books with the four headers, and keeps it on disk', async () => {
223
+ const s = setup();
224
+ await s.catalog.sync();
225
+ const [b] = await s.backend.requestBooking({ lines: [room('1001', 'DR1~BAR')] }, guest, who, {
226
+ kinds: ['high-floor', 'late-arrival'],
227
+ arrivingAt: '22:30',
228
+ });
229
+ expect(b?.status).toBe('confirmed');
230
+ expect(b?.confirmationCode).toMatch(/^R1001/);
231
+ expect(b?.holdUntil).toBeUndefined();
232
+ expect(b?.quote.total).toEqual({ minor: 68_600, currency: 'CNY' });
233
+ const paths = s.fake.calls.map((c) => c.path);
234
+ expect(paths.indexOf('/reservation/prebook')).toBeLessThan(paths.indexOf('/reservation/book'));
235
+ const book = s.fake.calls.find((c) => c.path === '/reservation/book');
236
+ expect(book?.headers).toMatchObject({
237
+ distributorid: 'CURLESS',
238
+ authorization: expect.stringMatching(/^Bearer /),
239
+ });
240
+ expect(book?.headers.traceid).toBeTruthy();
241
+ expect(book?.body).toMatchObject({
242
+ paymentType: 'NGPL',
243
+ contactPerson: { lastName: 'Zhang', firstName: 'Wei', email: 'wei@example.com' },
244
+ guestComment: '高楼层,晚到,预计22:30到店',
245
+ reservations: [
246
+ {
247
+ amountAfterTax: [328, 358],
248
+ guaranteePolicyCode: 'PL',
249
+ estimatedArrivalTime: '22:30',
250
+ adultCount: 2,
251
+ },
252
+ ],
253
+ });
254
+ expect(String((book?.body).distributorResId)).toMatch(/^CUR/);
255
+ // Survives a restart: the booking is found by a new process, by code and email.
256
+ const later = setup({ dir: s.dir });
257
+ await later.catalog.sync();
258
+ const found = await later.backend.findBooking(b?.confirmationCode ?? '', {
259
+ sessionId: 'other',
260
+ email: 'WEI@example.com',
261
+ });
262
+ expect(found?.id).toBe(b?.id);
263
+ expect(await later.backend.findBooking(b?.confirmationCode ?? '', { sessionId: 'third' })).toBeNull();
264
+ });
265
+ it('books nothing when prebook refuses, and says why', async () => {
266
+ const s = setup();
267
+ await s.catalog.sync();
268
+ s.fake.fail({ path: '/reservation/prebook', kind: 5109 });
269
+ await expect(s.backend.requestBooking({ lines: [room('1001', 'DR1~BAR')] }, guest, who)).rejects.toThrow(/Nothing was booked\..*no rooms left/);
270
+ expect(s.fake.calls.some((c) => c.path === '/reservation/book')).toBe(false);
271
+ });
272
+ it('an answer lost on the way back is found by the consistency query', async () => {
273
+ const s = setup();
274
+ await s.catalog.sync();
275
+ s.fake.fail({ path: '/reservation/book', kind: 'answer-lost' });
276
+ const [b] = await s.backend.requestBooking({ lines: [room('1001', 'DR1~BAR')] }, guest, who);
277
+ expect(b?.status).toBe('confirmed');
278
+ expect(b?.confirmationCode).toMatch(/^R1001/);
279
+ expect(s.fake.calls.filter((c) => c.path === '/reservation/consistency/query').length).toBeGreaterThan(0);
280
+ // Once, however many times it was asked about.
281
+ expect(s.fake.bookings.size).toBe(1);
282
+ });
283
+ it('a call that never arrived stays "requested" and fails after eight minutes of not-found', async () => {
284
+ const s = setup();
285
+ await s.catalog.sync();
286
+ s.fake.fail({ path: '/reservation/book', kind: 'unreachable' });
287
+ const [b] = await s.backend.requestBooking({ lines: [room('1001', 'DR1~BAR')] }, guest, who);
288
+ expect(b?.status).toBe('requested');
289
+ expect(b?.confirmationCode).toMatch(/^CUR/);
290
+ s.advance(PENDING_WINDOW_MS);
291
+ await s.reconciler.tick();
292
+ const after = s.store.get(b?.id ?? '');
293
+ expect(after?.status).toBe('failed');
294
+ expect(after?.pendingSince).toBeUndefined();
295
+ expect(after?.attention).toBeUndefined();
296
+ // At most sixteen queries in the window, as the documentation allows.
297
+ expect(s.fake.calls.filter((c) => c.path === '/reservation/consistency/query').length).toBeLessThanOrEqual(16);
298
+ });
299
+ it('when the follow-up itself cannot get through, a person is asked for', async () => {
300
+ const s = setup();
301
+ await s.catalog.sync();
302
+ s.fake.fail({ path: '/reservation/book', kind: 'unreachable' });
303
+ s.fake.fail({ path: '/reservation/consistency/query', kind: 'unreachable', times: 50 });
304
+ const [b] = await s.backend.requestBooking({ lines: [room('1001', 'DR1~BAR')] }, guest, who);
305
+ s.advance(PENDING_WINDOW_MS);
306
+ await s.reconciler.tick();
307
+ expect(s.store.get(b?.id ?? '')?.attention).toMatch(/within 24 hours/);
308
+ expect(s.log.join('\n')).toMatch(/NEEDS A PERSON/);
309
+ expect(s.backend.health()).toMatchObject({ needsAPerson: 1 });
310
+ });
311
+ it('a two-city trip whose second stay is refused takes the first back', async () => {
312
+ const s = setup();
313
+ await s.catalog.sync();
314
+ s.fake.fail({ path: '/reservation/book', kind: 5210, skip: 1 });
315
+ const trip = {
316
+ lines: [
317
+ room('1001', 'DR1~BAR'),
318
+ room('2002', 'DR1~BAR2', { checkIn: '2026-10-12', checkOut: '2026-10-14', guests: 2 }),
319
+ ],
320
+ };
321
+ await expect(s.backend.requestBooking(trip, guest, who)).rejects.toThrow(/Nothing was booked.*cancelled again/s);
322
+ const [first] = [...s.fake.bookings.values()];
323
+ expect(first?.status).toBe('HOTEL_CANCEL');
324
+ expect(await s.backend.listBookings(who)).toEqual([
325
+ expect.objectContaining({ status: 'cancelled', hotelId: '1001' }),
326
+ ]);
327
+ });
328
+ it("previews a cancellation in the rate's own terms, then cancels at Huazhu", async () => {
329
+ const s = setup();
330
+ await s.catalog.sync();
331
+ const [b] = await s.backend.requestBooking({ lines: [room('1001', 'DR1~BAR')] }, guest, who);
332
+ const code = b?.confirmationCode ?? '';
333
+ const p = await s.backend.previewCancellation(code, who);
334
+ expect(p).toMatchObject({
335
+ cancellable: true,
336
+ fee: { minor: 0 },
337
+ freeUntil: '2026-10-09T10:00:00.000Z',
338
+ });
339
+ expect(p?.rule).toMatch(/Free to cancel until 2026-10-09 18:00/);
340
+ expect(p?.rule).toMatch(/paid at the hotel/);
341
+ const c = await s.backend.cancelBooking(code, who);
342
+ expect(c?.status).toBe('cancelled');
343
+ expect(s.fake.bookings.get(code)?.status).toBe('HOTEL_CANCEL');
344
+ // Cancelling twice is an answer, not an error.
345
+ expect((await s.backend.cancelBooking(code, who))?.status).toBe('cancelled');
346
+ });
347
+ it('refuses to move a booking, in words that say what to do instead', async () => {
348
+ const s = setup();
349
+ await s.catalog.sync();
350
+ const [b] = await s.backend.requestBooking({ lines: [room('1001', 'DR1~BAR')] }, guest, who);
351
+ const p = await s.backend.previewChange(b?.confirmationCode ?? '', { checkIn: '2026-10-11' }, who);
352
+ expect(p).toMatchObject({ changeable: false });
353
+ expect(p?.rule).toMatch(/cancel it/);
354
+ });
355
+ it('a name too long for Huazhu is refused before anything is sent', async () => {
356
+ const s = setup();
357
+ await s.catalog.sync();
358
+ await expect(s.backend.requestBooking({ lines: [room('1001', 'DR1~BAR')] }, { name: 'Wolfeschlegelsteinhausenberger', email: 'a@b.co' }, who)).rejects.toThrow(/16 characters/);
359
+ expect(s.fake.calls.some((c) => c.path.startsWith('/reservation'))).toBe(false);
360
+ });
361
+ it('a system error is retried once with the same distributorResId, as the documentation advises', async () => {
362
+ const s = setup();
363
+ await s.catalog.sync();
364
+ s.fake.fail({ path: '/reservation/book', kind: 2001 });
365
+ const [b] = await s.backend.requestBooking({ lines: [room('1001', 'DR1~BAR')] }, guest, who);
366
+ expect(b?.status).toBe('confirmed');
367
+ const ids = s.fake.calls
368
+ .filter((c) => c.path === '/reservation/book')
369
+ .map((c) => c.body.distributorResId);
370
+ expect(ids).toHaveLength(2);
371
+ expect(new Set(ids).size).toBe(1);
372
+ });
373
+ it('says what it cannot do', () => {
374
+ const s = setup();
375
+ expect(s.backend.capabilities).toEqual({
376
+ members: false,
377
+ extras: false,
378
+ changes: false,
379
+ booking: 'pay-at-hotel',
380
+ });
381
+ });
382
+ });
383
+ describe('Huazhu client', () => {
384
+ const make = (respond) => {
385
+ let tokenCalls = 0;
386
+ const fetch = (async (input) => {
387
+ const url = String(input);
388
+ if (url.includes('/oauth/token')) {
389
+ tokenCalls += 1;
390
+ await new Promise((r) => setTimeout(r, 5));
391
+ return new Response(JSON.stringify({ access_token: `t${tokenCalls}`, expires_in: 3600 }), {
392
+ status: 200,
393
+ });
394
+ }
395
+ return respond(url);
396
+ });
397
+ const client = new HuazhuClient({
398
+ baseUrl: 'https://biz.test',
399
+ authUrl: 'https://auth.test',
400
+ credentials: { clientId: 'a', secret: 'b', distributorId: 'D' },
401
+ fetch,
402
+ });
403
+ return { client, tokenCalls: () => tokenCalls };
404
+ };
405
+ const ok = (content) => new Response(JSON.stringify({ code: 1000, content }), { status: 200 });
406
+ it('fetches ONE token for many calls at once - a second fetch would retire the first', async () => {
407
+ const m = make(() => ok([]));
408
+ await Promise.all([m.client.hotels(), m.client.hotels(), m.client.hotels()]);
409
+ expect(m.tokenCalls()).toBe(1);
410
+ });
411
+ it('a 4xx is an answer, a 5xx or a dropped connection is not', async () => {
412
+ const four = make(() => new Response(JSON.stringify({ code: 2004, message: 'Required field missing' }), {
413
+ status: 400,
414
+ }));
415
+ await expect(four.client.hotels()).rejects.toBeInstanceOf(HuazhuRefusal);
416
+ const five = make(() => new Response('bad gateway', { status: 502 }));
417
+ await expect(five.client.hotels()).rejects.toBeInstanceOf(HuazhuUnreachable);
418
+ const reset = make(() => {
419
+ throw new TypeError('fetch failed');
420
+ });
421
+ await expect(reset.client.hotels()).rejects.toBeInstanceOf(HuazhuUnreachable);
422
+ const garbled = make(() => new Response('<html>', { status: 200 }));
423
+ await expect(garbled.client.hotels()).rejects.toBeInstanceOf(HuazhuUnreachable);
424
+ });
425
+ it('a refusal carries the code, the message and the detail', async () => {
426
+ const m = make(() => new Response(JSON.stringify({
427
+ code: 5109,
428
+ message: 'No rooms available for requested dates',
429
+ responseDes: 'DR1',
430
+ }), { status: 200 }));
431
+ await expect(m.client.hotels()).rejects.toMatchObject({ code: 5109, detail: 'DR1' });
432
+ });
433
+ });
434
+ //# sourceMappingURL=huazhu-backend.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"huazhu-backend.test.js","sourceRoot":"","sources":["../../src/__tests__/huazhu-backend.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=huazhu-cancel-policy.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"huazhu-cancel-policy.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/huazhu-cancel-policy.test.ts"],"names":[],"mappings":""}