@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.
- package/README.md +35 -11
- package/dist/__tests__/__fixtures__/huazhu-fake.d.ts +2 -0
- package/dist/__tests__/__fixtures__/huazhu-fake.d.ts.map +1 -0
- package/dist/__tests__/__fixtures__/huazhu-fake.js +3 -0
- package/dist/__tests__/__fixtures__/huazhu-fake.js.map +1 -0
- package/dist/__tests__/huazhu-backend.test.d.ts +2 -0
- package/dist/__tests__/huazhu-backend.test.d.ts.map +1 -0
- package/dist/__tests__/huazhu-backend.test.js +434 -0
- package/dist/__tests__/huazhu-backend.test.js.map +1 -0
- package/dist/__tests__/huazhu-cancel-policy.test.d.ts +2 -0
- package/dist/__tests__/huazhu-cancel-policy.test.d.ts.map +1 -0
- package/dist/__tests__/huazhu-cancel-policy.test.js +82 -0
- package/dist/__tests__/huazhu-cancel-policy.test.js.map +1 -0
- package/dist/__tests__/huazhu-sandbox.test.d.ts +2 -0
- package/dist/__tests__/huazhu-sandbox.test.d.ts.map +1 -0
- package/dist/__tests__/huazhu-sandbox.test.js +172 -0
- package/dist/__tests__/huazhu-sandbox.test.js.map +1 -0
- package/dist/__tests__/huazhu-sellable.test.d.ts +2 -0
- package/dist/__tests__/huazhu-sellable.test.d.ts.map +1 -0
- package/dist/__tests__/huazhu-sellable.test.js +192 -0
- package/dist/__tests__/huazhu-sellable.test.js.map +1 -0
- package/dist/__tests__/server.test.js +129 -4
- package/dist/__tests__/server.test.js.map +1 -1
- package/dist/__tests__/tool-descriptions.test.js +85 -7
- package/dist/__tests__/tool-descriptions.test.js.map +1 -1
- package/dist/backend.d.ts +27 -0
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js +7 -0
- package/dist/backend.js.map +1 -1
- 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/config.d.ts +64 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/facilities.d.ts.map +1 -1
- package/dist/facilities.js +7 -5
- package/dist/facilities.js.map +1 -1
- package/dist/huazhu/backend.d.ts +40 -0
- package/dist/huazhu/backend.d.ts.map +1 -0
- package/dist/huazhu/backend.js +1318 -0
- package/dist/huazhu/backend.js.map +1 -0
- package/dist/huazhu/bookings.d.ts +81 -0
- package/dist/huazhu/bookings.d.ts.map +1 -0
- package/dist/huazhu/bookings.js +189 -0
- package/dist/huazhu/bookings.js.map +1 -0
- package/dist/huazhu/cancel-policy.d.ts +69 -0
- package/dist/huazhu/cancel-policy.d.ts.map +1 -0
- package/dist/huazhu/cancel-policy.js +201 -0
- package/dist/huazhu/cancel-policy.js.map +1 -0
- package/dist/huazhu/catalog.d.ts +75 -0
- package/dist/huazhu/catalog.d.ts.map +1 -0
- package/dist/huazhu/catalog.js +251 -0
- package/dist/huazhu/catalog.js.map +1 -0
- package/dist/huazhu/check.d.ts +5 -0
- package/dist/huazhu/check.d.ts.map +1 -0
- package/dist/huazhu/check.js +170 -0
- package/dist/huazhu/check.js.map +1 -0
- package/dist/huazhu/client.d.ts +100 -0
- package/dist/huazhu/client.d.ts.map +1 -0
- package/dist/huazhu/client.js +232 -0
- package/dist/huazhu/client.js.map +1 -0
- package/dist/huazhu/fake.d.ts +64 -0
- package/dist/huazhu/fake.d.ts.map +1 -0
- package/dist/huazhu/fake.js +365 -0
- package/dist/huazhu/fake.js.map +1 -0
- package/dist/huazhu/sandbox.d.ts +26 -0
- package/dist/huazhu/sandbox.d.ts.map +1 -0
- package/dist/huazhu/sandbox.js +289 -0
- package/dist/huazhu/sandbox.js.map +1 -0
- package/dist/huazhu/sellable.d.ts +81 -0
- package/dist/huazhu/sellable.d.ts.map +1 -0
- package/dist/huazhu/sellable.js +219 -0
- package/dist/huazhu/sellable.js.map +1 -0
- package/dist/huazhu/wire.d.ts +389 -0
- package/dist/huazhu/wire.d.ts.map +1 -0
- package/dist/huazhu/wire.js +72 -0
- package/dist/huazhu/wire.js.map +1 -0
- package/dist/index.js +18 -4
- package/dist/index.js.map +1 -1
- package/dist/legal.d.ts +4 -3
- package/dist/legal.d.ts.map +1 -1
- package/dist/legal.js +71 -30
- package/dist/legal.js.map +1 -1
- package/dist/lib.d.ts +8 -3
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +8 -1
- package/dist/lib.js.map +1 -1
- package/dist/server.d.ts +20 -8
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +132 -28
- package/dist/server.js.map +1 -1
- package/dist/surface.d.ts +2 -1
- package/dist/surface.d.ts.map +1 -1
- package/dist/surface.js +42 -10
- package/dist/surface.js.map +1 -1
- package/dist/tools.d.ts +33 -20
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +122 -11
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +21 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/vocab.d.ts +5 -0
- package/dist/vocab.d.ts.map +1 -1
- package/dist/vocab.js +2 -1
- package/dist/vocab.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { createServer } from 'node:http';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { addDays } from '../dates.js';
|
|
5
|
+
import { createFakeHuazhu, fakeHotel, product } from './fake.js';
|
|
6
|
+
const SEEDS = [
|
|
7
|
+
{
|
|
8
|
+
id: '1001',
|
|
9
|
+
name: '汉庭酒店(上海人民广场店)',
|
|
10
|
+
en: "Hanting Hotel Shanghai People's Square",
|
|
11
|
+
brand: '汉庭',
|
|
12
|
+
brandCode: 2,
|
|
13
|
+
province: ['310000', '上海市'],
|
|
14
|
+
city: ['310100', '上海市'],
|
|
15
|
+
county: '黄浦区',
|
|
16
|
+
address: '上海市黄浦区延安东路1号',
|
|
17
|
+
addressEn: "1 Yan'an East Road, Huangpu District, Shanghai",
|
|
18
|
+
near: '人民广场',
|
|
19
|
+
services: [[49, '中餐厅']],
|
|
20
|
+
base: 289,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: '1002',
|
|
24
|
+
name: '全季酒店(上海外滩店)',
|
|
25
|
+
en: 'JI Hotel Shanghai The Bund',
|
|
26
|
+
brand: '全季',
|
|
27
|
+
brandCode: 3,
|
|
28
|
+
province: ['310000', '上海市'],
|
|
29
|
+
city: ['310100', '上海市'],
|
|
30
|
+
county: '黄浦区',
|
|
31
|
+
address: '上海市黄浦区中山东一路2号',
|
|
32
|
+
addressEn: '2 East Zhongshan Road No.1, Huangpu District, Shanghai',
|
|
33
|
+
near: '外滩',
|
|
34
|
+
services: [
|
|
35
|
+
[71, '健身房'],
|
|
36
|
+
[49, '中餐厅'],
|
|
37
|
+
],
|
|
38
|
+
base: 499,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: '2001',
|
|
42
|
+
name: '全季酒店(北京国贸店)',
|
|
43
|
+
en: 'JI Hotel Beijing Guomao',
|
|
44
|
+
brand: '全季',
|
|
45
|
+
brandCode: 3,
|
|
46
|
+
province: ['110000', '北京市'],
|
|
47
|
+
city: ['110100', '北京市'],
|
|
48
|
+
county: '朝阳区',
|
|
49
|
+
address: '北京市朝阳区建国路1号',
|
|
50
|
+
addressEn: '1 Jianguo Road, Chaoyang District, Beijing',
|
|
51
|
+
near: '国贸',
|
|
52
|
+
services: [
|
|
53
|
+
[73, '游泳池'],
|
|
54
|
+
[71, '健身房'],
|
|
55
|
+
],
|
|
56
|
+
base: 469,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: '2002',
|
|
60
|
+
name: '桔子酒店(北京三里屯店)',
|
|
61
|
+
en: 'Orange Hotel Beijing Sanlitun',
|
|
62
|
+
brand: '桔子',
|
|
63
|
+
brandCode: 7,
|
|
64
|
+
province: ['110000', '北京市'],
|
|
65
|
+
city: ['110100', '北京市'],
|
|
66
|
+
county: '朝阳区',
|
|
67
|
+
address: '北京市朝阳区三里屯路3号',
|
|
68
|
+
addressEn: '3 Sanlitun Road, Chaoyang District, Beijing',
|
|
69
|
+
near: '三里屯',
|
|
70
|
+
services: [[71, '健身房']],
|
|
71
|
+
base: 529,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: '3001',
|
|
75
|
+
name: '漫心酒店(杭州西湖店)',
|
|
76
|
+
en: 'Manxin Hotel Hangzhou West Lake',
|
|
77
|
+
brand: '漫心',
|
|
78
|
+
brandCode: 11,
|
|
79
|
+
province: ['330000', '浙江省'],
|
|
80
|
+
city: ['330100', '杭州市'],
|
|
81
|
+
county: '西湖区',
|
|
82
|
+
address: '浙江省杭州市西湖区北山街4号',
|
|
83
|
+
addressEn: '4 Beishan Street, Xihu District, Hangzhou',
|
|
84
|
+
near: '西湖',
|
|
85
|
+
services: [
|
|
86
|
+
[49, '中餐厅'],
|
|
87
|
+
[75, '水疗'],
|
|
88
|
+
],
|
|
89
|
+
base: 699,
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: '4001',
|
|
93
|
+
name: '汉庭酒店(深圳福田会展中心店)',
|
|
94
|
+
en: 'Hanting Hotel Shenzhen Futian Convention Centre',
|
|
95
|
+
brand: '汉庭',
|
|
96
|
+
brandCode: 2,
|
|
97
|
+
province: ['440000', '广东省'],
|
|
98
|
+
city: ['440300', '深圳市'],
|
|
99
|
+
county: '福田区',
|
|
100
|
+
address: '广东省深圳市福田区福华三路5号',
|
|
101
|
+
addressEn: '5 Fuhua 3rd Road, Futian District, Shenzhen',
|
|
102
|
+
near: '会展中心',
|
|
103
|
+
services: [],
|
|
104
|
+
base: 259,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: '5001',
|
|
108
|
+
name: '花间堂(成都宽窄巷子店)',
|
|
109
|
+
en: 'Blossom House Chengdu Kuanzhai Alley',
|
|
110
|
+
brand: '花间堂',
|
|
111
|
+
brandCode: 21,
|
|
112
|
+
province: ['510000', '四川省'],
|
|
113
|
+
city: ['510100', '成都市'],
|
|
114
|
+
county: '青羊区',
|
|
115
|
+
address: '四川省成都市青羊区宽巷子6号',
|
|
116
|
+
addressEn: '6 Kuan Alley, Qingyang District, Chengdu',
|
|
117
|
+
near: '宽窄巷子',
|
|
118
|
+
services: [
|
|
119
|
+
[49, '中餐厅'],
|
|
120
|
+
[75, '水疗'],
|
|
121
|
+
],
|
|
122
|
+
base: 899,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: '6001',
|
|
126
|
+
name: '美仑酒店(广州珠江新城店)',
|
|
127
|
+
en: 'Meilun Hotel Guangzhou Zhujiang New Town',
|
|
128
|
+
brand: '美仑',
|
|
129
|
+
brandCode: 15,
|
|
130
|
+
province: ['440000', '广东省'],
|
|
131
|
+
city: ['440100', '广州市'],
|
|
132
|
+
county: '天河区',
|
|
133
|
+
address: '广东省广州市天河区珠江东路7号',
|
|
134
|
+
addressEn: '7 Zhujiang East Road, Tianhe District, Guangzhou',
|
|
135
|
+
near: '珠江新城',
|
|
136
|
+
services: [
|
|
137
|
+
[73, '游泳池'],
|
|
138
|
+
[71, '健身房'],
|
|
139
|
+
[49, '中餐厅'],
|
|
140
|
+
],
|
|
141
|
+
base: 759,
|
|
142
|
+
},
|
|
143
|
+
];
|
|
144
|
+
/** The invented hotels, shaped as Huazhu's /hotel answers them. No photographs: none of them exists. */
|
|
145
|
+
export const SANDBOX_HOTELS = SEEDS.map((s) => fakeHotel(s.id, {
|
|
146
|
+
hotelName: `【模拟】${s.name}`,
|
|
147
|
+
hotelNameEn: `[Sandbox] ${s.en}`,
|
|
148
|
+
brandCode: s.brandCode,
|
|
149
|
+
brandName: s.brand,
|
|
150
|
+
provinceNo: s.province[0],
|
|
151
|
+
provinceName: s.province[1],
|
|
152
|
+
cityNo: s.city[0],
|
|
153
|
+
cityName: s.city[1],
|
|
154
|
+
countyName: s.county,
|
|
155
|
+
hotelAddress: s.address,
|
|
156
|
+
hotelAddressEn: s.addressEn,
|
|
157
|
+
hotelWordIntroduce: '模拟数据:这家酒店不存在,只用于测试连接器。',
|
|
158
|
+
hotelServiceList: s.services.map(([childClassCode, childClassName]) => ({
|
|
159
|
+
childClassCode,
|
|
160
|
+
childClassName,
|
|
161
|
+
})),
|
|
162
|
+
hotelPhotoList: [],
|
|
163
|
+
hotelTrafficList: [
|
|
164
|
+
{ destinationType: '9', destinationName: s.near, destinationDistance: '500m' },
|
|
165
|
+
],
|
|
166
|
+
}));
|
|
167
|
+
/** Friday and Saturday nights cost more, as they do at a city hotel. */
|
|
168
|
+
const weekend = (d) => {
|
|
169
|
+
const day = new Date(`${d}T00:00:00Z`).getUTCDay();
|
|
170
|
+
return day === 5 || day === 6;
|
|
171
|
+
};
|
|
172
|
+
const priced = (base) => (d) => Math.round(base * (weekend(d) ? 1.15 : 1));
|
|
173
|
+
/** Three rates a hotel, fifty rooms of each a night: enough for many test bookings, since these never lapse. */
|
|
174
|
+
export const SANDBOX_RATES = Object.fromEntries(SEEDS.map((s) => [
|
|
175
|
+
s.id,
|
|
176
|
+
[
|
|
177
|
+
{
|
|
178
|
+
product: product('DR1', 'BAR', { rateCodeName: '门市价' }),
|
|
179
|
+
price: priced(s.base),
|
|
180
|
+
inventory: () => 50,
|
|
181
|
+
cancel: '6PM1D1N_100P',
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
product: product('DR1', 'BARB', { rateCodeName: '门市价含早' }),
|
|
185
|
+
price: priced(s.base + 40),
|
|
186
|
+
inventory: () => 50,
|
|
187
|
+
meal: { type: 'BB', count: 1 },
|
|
188
|
+
cancel: '6PM1D1N_100P',
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
product: product('TR1', 'BAR', { rateCodeName: '门市价' }),
|
|
192
|
+
price: priced(s.base + 20),
|
|
193
|
+
inventory: () => 50,
|
|
194
|
+
cancel: 'AD0_0',
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
]));
|
|
198
|
+
/** How long a booking is kept after its check-out, as the connector keeps its own copy. */
|
|
199
|
+
const KEEP_DAYS = 90;
|
|
200
|
+
export const startSandbox = (o = {}) => {
|
|
201
|
+
const now = o.now ?? Date.now;
|
|
202
|
+
const load = () => {
|
|
203
|
+
if (!o.stateFile)
|
|
204
|
+
return undefined;
|
|
205
|
+
try {
|
|
206
|
+
return JSON.parse(readFileSync(o.stateFile, 'utf8'));
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
const initial = load();
|
|
213
|
+
const fake = createFakeHuazhu({
|
|
214
|
+
hotels: SANDBOX_HOTELS,
|
|
215
|
+
rates: SANDBOX_RATES,
|
|
216
|
+
now,
|
|
217
|
+
...(o.clientId ? { clientId: o.clientId } : {}),
|
|
218
|
+
...(o.secret ? { secret: o.secret } : {}),
|
|
219
|
+
...(o.distributorId ? { distributorId: o.distributorId } : {}),
|
|
220
|
+
...(initial ? { state: initial } : {}),
|
|
221
|
+
});
|
|
222
|
+
const save = () => {
|
|
223
|
+
if (!o.stateFile)
|
|
224
|
+
return;
|
|
225
|
+
const today = new Date(now() + 8 * 3_600_000).toISOString().slice(0, 10);
|
|
226
|
+
const state = fake.snapshot();
|
|
227
|
+
state.bookings = state.bookings.filter((b) => addDays(b.request.reservations[0].checkout, KEEP_DAYS) >= today);
|
|
228
|
+
const tmp = `${o.stateFile}.tmp`;
|
|
229
|
+
writeFileSync(tmp, JSON.stringify(state));
|
|
230
|
+
renameSync(tmp, o.stateFile);
|
|
231
|
+
};
|
|
232
|
+
const server = createServer(async (req, res) => {
|
|
233
|
+
const url = new URL(req.url ?? '/', 'http://sandbox');
|
|
234
|
+
if (req.method === 'GET' && url.pathname === '/healthz') {
|
|
235
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
236
|
+
res.end(JSON.stringify({ ok: true, sandbox: true, hotels: SANDBOX_HOTELS.length }));
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const chunks = [];
|
|
240
|
+
for await (const c of req)
|
|
241
|
+
chunks.push(c);
|
|
242
|
+
const body = Buffer.concat(chunks).toString('utf8');
|
|
243
|
+
const headers = {};
|
|
244
|
+
for (const [k, v] of Object.entries(req.headers))
|
|
245
|
+
if (typeof v === 'string')
|
|
246
|
+
headers[k] = v;
|
|
247
|
+
try {
|
|
248
|
+
const answer = await fake.fetch(url.href, {
|
|
249
|
+
method: req.method ?? 'POST',
|
|
250
|
+
headers,
|
|
251
|
+
...(body ? { body } : {}),
|
|
252
|
+
});
|
|
253
|
+
if (url.pathname.startsWith('/reservation/'))
|
|
254
|
+
save();
|
|
255
|
+
const text = await answer.text();
|
|
256
|
+
res.writeHead(answer.status, {
|
|
257
|
+
'content-type': answer.headers.get('content-type') ?? 'application/json',
|
|
258
|
+
});
|
|
259
|
+
res.end(text);
|
|
260
|
+
// The path and the outcome only: the bodies carry guests' names and emails.
|
|
261
|
+
o.log?.(`${req.method} ${url.pathname} -> ${answer.status}`);
|
|
262
|
+
}
|
|
263
|
+
catch (err) {
|
|
264
|
+
res.writeHead(502, { 'content-type': 'text/plain' });
|
|
265
|
+
res.end('sandbox error');
|
|
266
|
+
o.log?.(`${req.method} ${url.pathname} -> error: ${err.message}`);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
return new Promise((resolve) => {
|
|
270
|
+
server.listen(o.port ?? 0, o.host ?? '0.0.0.0', () => resolve({
|
|
271
|
+
server,
|
|
272
|
+
port: server.address().port,
|
|
273
|
+
close: () => new Promise((done) => server.close(() => done())),
|
|
274
|
+
}));
|
|
275
|
+
});
|
|
276
|
+
};
|
|
277
|
+
// `node dist/huazhu/sandbox.js` - the deployment's simulated Huazhu.
|
|
278
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
279
|
+
const env = process.env;
|
|
280
|
+
startSandbox({
|
|
281
|
+
port: Number(env.PORT ?? 8100),
|
|
282
|
+
...(env.SANDBOX_STATE_FILE ? { stateFile: env.SANDBOX_STATE_FILE } : {}),
|
|
283
|
+
...(env.HUAZHU_CLIENT_ID ? { clientId: env.HUAZHU_CLIENT_ID } : {}),
|
|
284
|
+
...(env.HUAZHU_CLIENT_SECRET ? { secret: env.HUAZHU_CLIENT_SECRET } : {}),
|
|
285
|
+
...(env.HUAZHU_DISTRIBUTOR_ID ? { distributorId: env.HUAZHU_DISTRIBUTOR_ID } : {}),
|
|
286
|
+
log: (l) => console.log(l),
|
|
287
|
+
}).then(({ port }) => console.log(`simulated Huazhu distributor API - NOT Huazhu - ${SANDBOX_HOTELS.length} invented hotels on :${port}`));
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/huazhu/sandbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { type BookWindow, type DailyOffer, type HotelRoomType, type PaymentType, type Product, type RateInfo } from './wire.js';
|
|
2
|
+
/** Arrays in one ARI answer, one element per date from `start`. */
|
|
3
|
+
export type AriWindow = {
|
|
4
|
+
start: string;
|
|
5
|
+
offer: DailyOffer;
|
|
6
|
+
/** Rooms left, per date, from /ari/daily/inventory. */
|
|
7
|
+
inventory?: (number | null)[];
|
|
8
|
+
};
|
|
9
|
+
export type SellContext = {
|
|
10
|
+
checkIn: string;
|
|
11
|
+
checkOut: string;
|
|
12
|
+
/** Per room. The connector's `Stay.guests`. */
|
|
13
|
+
adults: number;
|
|
14
|
+
rooms: number;
|
|
15
|
+
/** The hotel's own date and time of day, now. */
|
|
16
|
+
today: string;
|
|
17
|
+
clock: string;
|
|
18
|
+
paymentType: PaymentType;
|
|
19
|
+
/** Gated tags the contract lets this deployment show. */
|
|
20
|
+
allowTags: ReadonlySet<string>;
|
|
21
|
+
};
|
|
22
|
+
export type Sellable = {
|
|
23
|
+
ok: true;
|
|
24
|
+
product: Product;
|
|
25
|
+
currency: string;
|
|
26
|
+
/** One per night, in the currency's major units, as Huazhu sent them. */
|
|
27
|
+
after: number[];
|
|
28
|
+
/** One per night, or absent when Huazhu did not send every night's. */
|
|
29
|
+
before?: number[];
|
|
30
|
+
rack?: number[];
|
|
31
|
+
guaranteeCode: string;
|
|
32
|
+
cancelCode: string;
|
|
33
|
+
/** The meal on the rate, in words, or absent for room only. */
|
|
34
|
+
meal?: string;
|
|
35
|
+
/** How many of that meal a night, on the arrival night. */
|
|
36
|
+
mealCount: number;
|
|
37
|
+
roomsLeft: number;
|
|
38
|
+
/** Promotions sell at most 3 rooms a booking, list rates 10. */
|
|
39
|
+
maxRooms: number;
|
|
40
|
+
sleeps: number;
|
|
41
|
+
};
|
|
42
|
+
export type Unsellable = {
|
|
43
|
+
ok: false;
|
|
44
|
+
/**
|
|
45
|
+
* Which kind of no, so a hotel with nothing to sell can say the most useful
|
|
46
|
+
* one: a party too big is fixed by a second room, a closed date by another
|
|
47
|
+
* date, prepaid-only by nothing this connector can do.
|
|
48
|
+
*/
|
|
49
|
+
kind: 'party' | 'closed' | 'stay-rule' | 'sold-out' | 'too-many-rooms' | 'prepaid' | 'no-price';
|
|
50
|
+
why: string;
|
|
51
|
+
};
|
|
52
|
+
/** Offered to nobody here: hour rooms, and rates the contract shows to some guests only. */
|
|
53
|
+
export declare const offeredAtAll: (p: Product, allowTags: ReadonlySet<string>) => boolean;
|
|
54
|
+
/** The price entry for this many adults - the smallest one that covers them. */
|
|
55
|
+
export declare const rateFor: (rates: RateInfo[], adults: number) => RateInfo | undefined;
|
|
56
|
+
/** The most people one room of this product sleeps, from everything Huazhu says about it. */
|
|
57
|
+
export declare const sleepsOf: (p: Product, offer: DailyOffer | undefined, rt?: HotelRoomType) => number;
|
|
58
|
+
/**
|
|
59
|
+
* "预订窗口 … 非此时间范围内不展示该报价": outside its booking window a rate is
|
|
60
|
+
* not shown at all. A night-snack rate sells from 20:00; at 14:00 it does not
|
|
61
|
+
* exist.
|
|
62
|
+
*/
|
|
63
|
+
export declare const bookableNow: (w: BookWindow | undefined, checkIn: string, clock: string) => boolean;
|
|
64
|
+
/**
|
|
65
|
+
* One rate, one stay: sellable with its figures, or the reason it is not.
|
|
66
|
+
*
|
|
67
|
+
* `window` must cover every night AND the departure date - "close to
|
|
68
|
+
* departure" is a restriction on the day the guest leaves.
|
|
69
|
+
*/
|
|
70
|
+
export declare const sell: (product: Product, w: AriWindow, roomType: HotelRoomType | undefined, c: SellContext) => Sellable | Unsellable;
|
|
71
|
+
/**
|
|
72
|
+
* Cut a span of dates into the pieces the ARI endpoints accept: at most thirty
|
|
73
|
+
* dates each, both ends included ("endDate-startDate=29").
|
|
74
|
+
*/
|
|
75
|
+
export declare const ariRanges: (start: string, end: string) => {
|
|
76
|
+
start: string;
|
|
77
|
+
end: string;
|
|
78
|
+
}[];
|
|
79
|
+
/** The hotel's time of day, HH:MM. */
|
|
80
|
+
export declare const clockAt: (now: number, tz: string) => string;
|
|
81
|
+
//# sourceMappingURL=sellable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sellable.d.ts","sourceRoot":"","sources":["../../src/huazhu/sellable.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,UAAU,EAEf,KAAK,aAAa,EAGlB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,QAAQ,EACd,MAAM,WAAW,CAAC;AAanB,mEAAmE;AACnE,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,UAAU,CAAC;IAClB,uDAAuD;IACvD,SAAS,CAAC,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,WAAW,CAAC;IACzB,yDAAyD;IACzD,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,IAAI,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,KAAK,CAAC;IACV;;;;OAIG;IACH,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,gBAAgB,GAAG,SAAS,GAAG,UAAU,CAAC;IAChG,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,4FAA4F;AAC5F,eAAO,MAAM,YAAY,GAAI,GAAG,OAAO,EAAE,WAAW,WAAW,CAAC,MAAM,CAAC,KAAG,OACsB,CAAC;AAMjG,gFAAgF;AAChF,eAAO,MAAM,OAAO,GAAI,OAAO,QAAQ,EAAE,EAAE,QAAQ,MAAM,KAAG,QAAQ,GAAG,SAGd,CAAC;AAE1D,6FAA6F;AAC7F,eAAO,MAAM,QAAQ,GAAI,GAAG,OAAO,EAAE,OAAO,UAAU,GAAG,SAAS,EAAE,KAAK,aAAa,KAAG,MAUxF,CAAC;AAOF;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,GAAG,UAAU,GAAG,SAAS,EAAE,SAAS,MAAM,EAAE,OAAO,MAAM,KAAG,OAUvF,CAAC;AAUF;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GACf,SAAS,OAAO,EAChB,GAAG,SAAS,EACZ,UAAU,aAAa,GAAG,SAAS,EACnC,GAAG,WAAW,KACb,QAAQ,GAAG,UA8Ib,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,EAAE,KAAK,MAAM,KAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAOpF,CAAC;AAEF,sCAAsC;AACtC,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,EAAE,IAAI,MAAM,KAAG,MAWjD,CAAC"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { addDays, eachNight, nights } from '../dates.js';
|
|
2
|
+
import { GATED_TAGS, MEAL_PLANS, PAYMENT_FOR_GUARANTEE, } from './wire.js';
|
|
3
|
+
/** Offered to nobody here: hour rooms, and rates the contract shows to some guests only. */
|
|
4
|
+
export const offeredAtAll = (p, allowTags) => p.checkinType === 'DAY' && !(p.tags ?? []).some((t) => GATED_TAGS.has(t) && !allowTags.has(t));
|
|
5
|
+
/** "Not published" is read as not published: the example's 999 is nobody's room. */
|
|
6
|
+
const published = (n) => typeof n === 'number' && n > 0 && n < 99 ? n : undefined;
|
|
7
|
+
/** The price entry for this many adults - the smallest one that covers them. */
|
|
8
|
+
export const rateFor = (rates, adults) => [...rates]
|
|
9
|
+
.filter((r) => Number(r.maxAdultCount) >= adults)
|
|
10
|
+
.sort((a, b) => a.maxAdultCount - b.maxAdultCount)[0];
|
|
11
|
+
/** The most people one room of this product sleeps, from everything Huazhu says about it. */
|
|
12
|
+
export const sleepsOf = (p, offer, rt) => {
|
|
13
|
+
const said = [
|
|
14
|
+
published(p.occupancy?.maxOccupancy),
|
|
15
|
+
published(p.occupancy?.maxAdult),
|
|
16
|
+
published(rt?.maxOccupancy),
|
|
17
|
+
published(rt?.maxAdult),
|
|
18
|
+
].filter((n) => n !== undefined);
|
|
19
|
+
if (said.length)
|
|
20
|
+
return Math.min(...said);
|
|
21
|
+
const priced = (offer?.rates ?? []).map((r) => Number(r.maxAdultCount)).filter((n) => n > 0);
|
|
22
|
+
return priced.length ? Math.max(...priced) : 2;
|
|
23
|
+
};
|
|
24
|
+
const within = (clock, from, to) => {
|
|
25
|
+
const pad = (t) => (t.length === 4 ? `0${t}` : t);
|
|
26
|
+
return (!from || clock >= pad(from)) && (!to || clock <= pad(to));
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* "预订窗口 … 非此时间范围内不展示该报价": outside its booking window a rate is
|
|
30
|
+
* not shown at all. A night-snack rate sells from 20:00; at 14:00 it does not
|
|
31
|
+
* exist.
|
|
32
|
+
*/
|
|
33
|
+
export const bookableNow = (w, checkIn, clock) => {
|
|
34
|
+
if (!w)
|
|
35
|
+
return true;
|
|
36
|
+
const override = (w.override ?? []).find((o) => (!o.startDate || checkIn >= o.startDate) && (!o.endDate || checkIn <= o.endDate));
|
|
37
|
+
const rule = override ?? w;
|
|
38
|
+
if (rule.startDate && checkIn < rule.startDate)
|
|
39
|
+
return false;
|
|
40
|
+
if (rule.endDate && checkIn > rule.endDate)
|
|
41
|
+
return false;
|
|
42
|
+
if ((rule.excludedDate ?? []).includes(checkIn))
|
|
43
|
+
return false;
|
|
44
|
+
return within(clock, rule.eachDayStartTime, rule.eachDayEndTime);
|
|
45
|
+
};
|
|
46
|
+
const num = (v) => typeof v === 'number' && Number.isFinite(v) ? v : undefined;
|
|
47
|
+
/** For the upper limits: null, or zero as the example writes "no limit", is no limit. */
|
|
48
|
+
const cap = (v) => {
|
|
49
|
+
const n = num(v);
|
|
50
|
+
return n !== undefined && n > 0 ? n : undefined;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* One rate, one stay: sellable with its figures, or the reason it is not.
|
|
54
|
+
*
|
|
55
|
+
* `window` must cover every night AND the departure date - "close to
|
|
56
|
+
* departure" is a restriction on the day the guest leaves.
|
|
57
|
+
*/
|
|
58
|
+
export const sell = (product, w, roomType, c) => {
|
|
59
|
+
const { offer } = w;
|
|
60
|
+
const n = nights(c.checkIn, c.checkOut);
|
|
61
|
+
const at = (day) => nights(w.start, day);
|
|
62
|
+
const first = at(c.checkIn);
|
|
63
|
+
const leave = at(c.checkOut);
|
|
64
|
+
const r = offer.restriction;
|
|
65
|
+
const nightsIdx = eachNight(c.checkIn, c.checkOut).map(at);
|
|
66
|
+
const sleeps = sleepsOf(product, offer, roomType);
|
|
67
|
+
const rate = rateFor(offer.rates ?? [], c.adults);
|
|
68
|
+
if (c.adults > sleeps || !rate) {
|
|
69
|
+
return { ok: false, kind: 'party', why: `sleeps ${sleeps}` };
|
|
70
|
+
}
|
|
71
|
+
if (nightsIdx.some((i) => r.close?.[i] === true)) {
|
|
72
|
+
return { ok: false, kind: 'closed', why: 'not sold on one of those nights' };
|
|
73
|
+
}
|
|
74
|
+
if (r.cta?.[first] === true) {
|
|
75
|
+
return { ok: false, kind: 'stay-rule', why: `no arrivals on ${c.checkIn}` };
|
|
76
|
+
}
|
|
77
|
+
if (r.ctd?.[leave] === true) {
|
|
78
|
+
return { ok: false, kind: 'stay-rule', why: `no departures on ${c.checkOut}` };
|
|
79
|
+
}
|
|
80
|
+
const minArr = num(r.minStayArrival?.[first]);
|
|
81
|
+
if (minArr !== undefined && n < minArr) {
|
|
82
|
+
return {
|
|
83
|
+
ok: false,
|
|
84
|
+
kind: 'stay-rule',
|
|
85
|
+
why: `arriving ${c.checkIn} needs at least ${minArr} nights`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const maxArr = cap(r.maxStayArrival?.[first]);
|
|
89
|
+
if (maxArr !== undefined && n > maxArr) {
|
|
90
|
+
return {
|
|
91
|
+
ok: false,
|
|
92
|
+
kind: 'stay-rule',
|
|
93
|
+
why: `arriving ${c.checkIn} allows at most ${maxArr} nights`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
for (const i of nightsIdx) {
|
|
97
|
+
const min = num(r.minStayThrough?.[i]);
|
|
98
|
+
if (min !== undefined && n < min) {
|
|
99
|
+
return {
|
|
100
|
+
ok: false,
|
|
101
|
+
kind: 'stay-rule',
|
|
102
|
+
why: `a stay over ${addDays(w.start, i)} needs at least ${min} nights`,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const max = cap(r.maxStayThrough?.[i]);
|
|
106
|
+
if (max !== undefined && n > max) {
|
|
107
|
+
return {
|
|
108
|
+
ok: false,
|
|
109
|
+
kind: 'stay-rule',
|
|
110
|
+
why: `a stay over ${addDays(w.start, i)} allows at most ${max} nights`,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const ahead = nights(c.today, c.checkIn);
|
|
115
|
+
const minAdv = num(r.minAdvanceDay?.[first]);
|
|
116
|
+
if (minAdv !== undefined && ahead < minAdv) {
|
|
117
|
+
return { ok: false, kind: 'stay-rule', why: `must be booked at least ${minAdv} days ahead` };
|
|
118
|
+
}
|
|
119
|
+
const maxAdv = cap(r.maxAdvanceDay?.[first]);
|
|
120
|
+
if (maxAdv !== undefined && ahead > maxAdv) {
|
|
121
|
+
return { ok: false, kind: 'stay-rule', why: `can be booked at most ${maxAdv} days ahead` };
|
|
122
|
+
}
|
|
123
|
+
// Full-pattern length of stay: one character per length, the last meaning
|
|
124
|
+
// "this many or more" - "1110111" refuses exactly four nights.
|
|
125
|
+
const fplos = r.fplos?.[first];
|
|
126
|
+
if (fplos) {
|
|
127
|
+
const ch = fplos[Math.min(n, fplos.length) - 1];
|
|
128
|
+
if (ch !== '1') {
|
|
129
|
+
return {
|
|
130
|
+
ok: false,
|
|
131
|
+
kind: 'stay-rule',
|
|
132
|
+
why: `${n} night${n === 1 ? '' : 's'} is not a length this rate sells from ${c.checkIn}`,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const after = nightsIdx.map((i) => num(rate.amountAfterTax?.[i]));
|
|
137
|
+
if (after.some((x) => x === undefined || x <= 0)) {
|
|
138
|
+
return { ok: false, kind: 'no-price', why: 'no price for one of those nights' };
|
|
139
|
+
}
|
|
140
|
+
const beforeRaw = nightsIdx.map((i) => num(rate.amountBeforeTax?.[i]));
|
|
141
|
+
const before = beforeRaw.every((x) => x !== undefined && x > 0)
|
|
142
|
+
? beforeRaw
|
|
143
|
+
: undefined;
|
|
144
|
+
const rackRaw = nightsIdx.map((i) => num(rate.rackRate?.[i]));
|
|
145
|
+
const rack = rackRaw.every((x) => x !== undefined && x > 0) ? rackRaw : undefined;
|
|
146
|
+
const left = nightsIdx.map((i) => num(w.inventory?.[i]) ?? 0);
|
|
147
|
+
const roomsLeft = Math.max(0, Math.min(...left));
|
|
148
|
+
const maxRooms = product.promotion ? 3 : 10;
|
|
149
|
+
if (c.rooms > maxRooms) {
|
|
150
|
+
return {
|
|
151
|
+
ok: false,
|
|
152
|
+
kind: 'too-many-rooms',
|
|
153
|
+
why: `this rate books at most ${maxRooms} rooms at a time`,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (roomsLeft < c.rooms) {
|
|
157
|
+
return {
|
|
158
|
+
ok: false,
|
|
159
|
+
kind: 'sold-out',
|
|
160
|
+
why: roomsLeft === 0 ? 'none left' : `only ${roomsLeft} left`,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
// ⚠️ THE ARRIVAL DATE'S TERMS ARE THE BOOKING'S: "按照预订入住日规则为准进行下单".
|
|
164
|
+
const guaranteeCode = offer.guaranteePolicies?.[first]?.code ?? '';
|
|
165
|
+
const cancelCode = offer.cancelPolicies?.[first]?.code ?? '';
|
|
166
|
+
if (!(PAYMENT_FOR_GUARANTEE[guaranteeCode] ?? []).includes(c.paymentType)) {
|
|
167
|
+
return {
|
|
168
|
+
ok: false,
|
|
169
|
+
kind: 'prepaid',
|
|
170
|
+
why: guaranteeCode === 'PN'
|
|
171
|
+
? 'this rate is paid in advance'
|
|
172
|
+
: `this rate is not sold as ${c.paymentType === 'NGPL' ? 'pay at the hotel' : c.paymentType}`,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
const mealCount = num(offer.mealPlanCounts?.[first]) ?? 0;
|
|
176
|
+
const meal = offer.mealPlanType !== 'RO' && mealCount > 0 ? MEAL_PLANS[offer.mealPlanType] : undefined;
|
|
177
|
+
return {
|
|
178
|
+
ok: true,
|
|
179
|
+
product,
|
|
180
|
+
currency: offer.currencyCode || 'CNY',
|
|
181
|
+
after: after,
|
|
182
|
+
...(before ? { before } : {}),
|
|
183
|
+
...(rack ? { rack } : {}),
|
|
184
|
+
guaranteeCode,
|
|
185
|
+
cancelCode,
|
|
186
|
+
...(meal ? { meal } : {}),
|
|
187
|
+
mealCount: meal ? mealCount : 0,
|
|
188
|
+
roomsLeft,
|
|
189
|
+
maxRooms,
|
|
190
|
+
sleeps,
|
|
191
|
+
};
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* Cut a span of dates into the pieces the ARI endpoints accept: at most thirty
|
|
195
|
+
* dates each, both ends included ("endDate-startDate=29").
|
|
196
|
+
*/
|
|
197
|
+
export const ariRanges = (start, end) => {
|
|
198
|
+
const out = [];
|
|
199
|
+
for (let s = start; s <= end; s = addDays(s, 30)) {
|
|
200
|
+
const e = addDays(s, 29);
|
|
201
|
+
out.push({ start: s, end: e < end ? e : end });
|
|
202
|
+
}
|
|
203
|
+
return out;
|
|
204
|
+
};
|
|
205
|
+
/** The hotel's time of day, HH:MM. */
|
|
206
|
+
export const clockAt = (now, tz) => {
|
|
207
|
+
try {
|
|
208
|
+
return new Intl.DateTimeFormat('en-GB', {
|
|
209
|
+
timeZone: tz,
|
|
210
|
+
hour: '2-digit',
|
|
211
|
+
minute: '2-digit',
|
|
212
|
+
hourCycle: 'h23',
|
|
213
|
+
}).format(now);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
return new Date(now).toISOString().slice(11, 16);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
//# sourceMappingURL=sellable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sellable.js","sourceRoot":"","sources":["../../src/huazhu/sellable.ts"],"names":[],"mappings":"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"}
|