@curless/hotel-storefront 0.34.0 → 0.35.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/dist/aggregate/make.d.ts.map +1 -1
- package/dist/aggregate/make.js +7 -1
- package/dist/aggregate/make.js.map +1 -1
- package/dist/backend.d.ts +2 -2
- package/dist/backend.d.ts.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 +24 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/huazhu/backend.d.ts +2 -2
- package/dist/huazhu/backend.d.ts.map +1 -1
- package/dist/huazhu/backend.js +119 -10
- package/dist/huazhu/backend.js.map +1 -1
- package/dist/huazhu/bookings.d.ts +2 -0
- package/dist/huazhu/bookings.d.ts.map +1 -1
- package/dist/huazhu/bookings.js.map +1 -1
- package/dist/huazhu/catalog.d.ts +7 -1
- package/dist/huazhu/catalog.d.ts.map +1 -1
- package/dist/huazhu/catalog.js +8 -4
- package/dist/huazhu/catalog.js.map +1 -1
- package/dist/huazhu/make.d.ts.map +1 -1
- package/dist/huazhu/make.js +44 -13
- package/dist/huazhu/make.js.map +1 -1
- package/dist/legal.d.ts.map +1 -1
- package/dist/legal.js +131 -83
- package/dist/legal.js.map +1 -1
- package/dist/payments/checkout.d.ts +49 -1
- package/dist/payments/checkout.d.ts.map +1 -1
- package/dist/payments/checkout.js +9 -0
- package/dist/payments/checkout.js.map +1 -1
- package/dist/payments/fake-stripe.d.ts +37 -0
- package/dist/payments/fake-stripe.d.ts.map +1 -0
- package/dist/payments/fake-stripe.js +123 -0
- package/dist/payments/fake-stripe.js.map +1 -0
- package/dist/payments/stripe-checkout.d.ts +44 -0
- package/dist/payments/stripe-checkout.d.ts.map +1 -0
- package/dist/payments/stripe-checkout.js +166 -0
- package/dist/payments/stripe-checkout.js.map +1 -0
- package/dist/server.d.ts +2 -2
- package/dist/server.js +2 -2
- package/dist/surface.d.ts.map +1 -1
- package/dist/surface.js +34 -20
- package/dist/surface.js.map +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +45 -23
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/vocab.d.ts +20 -0
- package/dist/vocab.d.ts.map +1 -1
- package/dist/vocab.js +25 -2
- package/dist/vocab.js.map +1 -1
- package/package.json +1 -1
package/dist/tools.js
CHANGED
|
@@ -8,7 +8,7 @@ import { withTraditional } from './names.js';
|
|
|
8
8
|
import { MAX_COMPARED, MAX_CONS, MAX_DAYS, MAX_ITEMS_PER_DAY, MAX_MOMENTS, MAX_PROS, buildItinerary, candidatesFor, compareHotels, namesMoreThanOne, } from './present.js';
|
|
9
9
|
import { regionOf } from './regions.js';
|
|
10
10
|
import { MAX_EXTRA_QUANTITY, MAX_ROOMS_PER_LINE, TRIP_TTL_MS, clampCount, shownOf, tripKey, } from './trip.js';
|
|
11
|
-
import { DEMO_NOTE, branded, catalogue, upFirst } from './vocab.js';
|
|
11
|
+
import { DEMO_NOTE, branded, catalogue, noteFor, upFirst } from './vocab.js';
|
|
12
12
|
// The eleven things a guest can do: find hotels, look at one on dates, see what
|
|
13
13
|
// else it offers, build a trip, ask for the rooms, and deal with a booking they
|
|
14
14
|
// already have.
|
|
@@ -208,11 +208,15 @@ const forCapabilities = (tools, n, v, caps) => {
|
|
|
208
208
|
// ⚠️ A SANDBOX BOOKS NOTHING REAL, and its description says so
|
|
209
209
|
// itself: the instructions carried "test environment" while this
|
|
210
210
|
// line still promised "the hotel's own reservation" (2026-09-30).
|
|
211
|
-
description: v.
|
|
212
|
-
? `Makes a booking in
|
|
211
|
+
description: v.test
|
|
212
|
+
? `Makes a test booking in ${v.brand}'s own test system, for testing: each stay gets its own confirmation code there, and none of it holds a room for anyone or is a stay anyone goes to. ${caps.prepaid
|
|
213
213
|
? 'A rate marked paid in advance is booked on its own, and not at once: the answer gives a card page in test mode and the time it is paid by, and the stay is booked once it is paid - no card is collected here. Every other rate is paid by nobody.'
|
|
214
214
|
: 'No payment is taken and no card is collected.'} All of the trip is booked or none of it. Preferences - a bed type, a floor, a late arrival - ride along on the booking as requests.`
|
|
215
|
-
:
|
|
215
|
+
: v.sandbox
|
|
216
|
+
? `Makes a booking in a simulated copy of ${v.brand}'s booking system, for testing: each stay gets its own confirmation code there, and none of it is a ${v.brand} reservation or holds a real room. ${caps.prepaid
|
|
217
|
+
? 'A rate marked paid in advance is booked on its own, and not at once: the answer gives a card page in test mode and the time it is paid by, and the stay is booked once it is paid - no card is collected here. Every other rate is paid by nobody.'
|
|
218
|
+
: 'No payment is taken and no card is collected.'} All of the trip is booked or none of it. Preferences - a bed type, a floor, a late arrival - ride along on the booking as requests.`
|
|
219
|
+
: `Books the trip's rooms with ${v.brand} for a named guest: each stay becomes the hotel's own reservation, with its own confirmation code, paid at the hotel. No payment is taken here and no card is collected. All of the trip is booked or none of it. Preferences - a bed type, a floor, a late arrival - ride along on the booking as requests the desk tries to meet.`,
|
|
216
220
|
};
|
|
217
221
|
}
|
|
218
222
|
}
|
|
@@ -1292,12 +1296,14 @@ const holderOf = (deps, supplier) => {
|
|
|
1292
1296
|
caps: s.capabilities,
|
|
1293
1297
|
demo: s.mode !== 'live',
|
|
1294
1298
|
sandbox: s.mode === 'sandbox',
|
|
1299
|
+
test: s.mode === 'test',
|
|
1295
1300
|
};
|
|
1296
1301
|
return {
|
|
1297
1302
|
name: deps.vocab.brand,
|
|
1298
1303
|
caps: deps.backend.capabilities ?? FULL_CAPABILITIES,
|
|
1299
1304
|
demo: deps.vocab.demo,
|
|
1300
1305
|
sandbox: !!deps.vocab.sandbox,
|
|
1306
|
+
test: !!deps.vocab.test,
|
|
1301
1307
|
};
|
|
1302
1308
|
};
|
|
1303
1309
|
/**
|
|
@@ -1332,7 +1338,9 @@ const paidLine = (deps, b) => {
|
|
|
1332
1338
|
const amount = formatMoney(p.amount);
|
|
1333
1339
|
const test = h.sandbox
|
|
1334
1340
|
? ' This is a test: the card page is in test mode, no real money moves, and the booking is in the simulated system.'
|
|
1335
|
-
:
|
|
1341
|
+
: h.test
|
|
1342
|
+
? ` This is a test: the card page is in test mode, no real money moves, and the booking is a test booking in ${h.name}'s test system.`
|
|
1343
|
+
: '';
|
|
1336
1344
|
switch (p.status) {
|
|
1337
1345
|
case 'awaiting':
|
|
1338
1346
|
return `**Not booked yet, and nothing paid.** ${amount} is paid on the card page by ${p.payByLocal ?? p.payBy} hotel time: ${p.url}. Once it is paid the stay is booked with ${h.name}, and ${deps.tools.listBookings} shows it; unpaid by then, the page closes and nothing is booked or charged.${test}`;
|
|
@@ -1372,6 +1380,8 @@ const bookedLine = (deps, b) => {
|
|
|
1372
1380
|
if (h.caps.booking === 'pay-at-hotel') {
|
|
1373
1381
|
if (h.sandbox)
|
|
1374
1382
|
return `${total} in the simulated system. **This is a test booking** - not a ${h.name} reservation: no room is held and nothing is paid, now or at any hotel.`;
|
|
1383
|
+
if (h.test)
|
|
1384
|
+
return `${total} in ${h.name}'s test system. **This is a test booking** - it holds no room for anyone, nothing is paid, now or at any hotel, and nobody needs to go there.`;
|
|
1375
1385
|
return b.status === 'requested'
|
|
1376
1386
|
? `${total} all in, to be paid at the hotel. ${h.name} has not confirmed this booking yet - that takes up to eight minutes, and ${deps.tools.listBookings} shows when it has. Nothing has been charged.`
|
|
1377
1387
|
: `${total} all in, paid at the hotel. **Nothing has been charged here** - this is ${h.name}'s own reservation, kept until it is cancelled, and ${b.guest.name} pays at check-in.`;
|
|
@@ -1413,6 +1423,11 @@ const common = (deps, key) => {
|
|
|
1413
1423
|
// In a market each group says whether it needs a phone (`market.suppliers`).
|
|
1414
1424
|
...(caps.requiresPhone && !deps.backend.suppliers ? { phoneRequired: true } : {}),
|
|
1415
1425
|
...(deps.vocab.sandbox ? { sandbox: true } : {}),
|
|
1426
|
+
// The group's own test system: the card says "test", never "simulated" -
|
|
1427
|
+
// and where it sells rates paid in advance, that those are paid with a
|
|
1428
|
+
// test card, never that "nothing is paid" (华住, 2026-10-15).
|
|
1429
|
+
...(deps.vocab.test ? { test: true } : {}),
|
|
1430
|
+
...(deps.vocab.test && caps.prepaid ? { testPays: true } : {}),
|
|
1416
1431
|
...(caps.programme ? { programme: caps.programme } : {}),
|
|
1417
1432
|
...(caps.codePrefix ? { codePrefix: caps.codePrefix } : {}),
|
|
1418
1433
|
// Sells rooms by the hour: the card draws its Overnight / By the hour
|
|
@@ -1424,7 +1439,7 @@ const common = (deps, key) => {
|
|
|
1424
1439
|
? { market: { name: deps.vocab.brand, suppliers: deps.backend.suppliers() } }
|
|
1425
1440
|
: {}),
|
|
1426
1441
|
vocab: { noun: deps.vocab.noun, nounPlural: deps.vocab.nounPlural },
|
|
1427
|
-
...(deps.vocab.demo ? { demo: true, demoNote:
|
|
1442
|
+
...(deps.vocab.demo ? { demo: true, demoNote: noteFor(deps.vocab) } : { demo: false }),
|
|
1428
1443
|
...(key ? memberBadge(deps, key) : {}),
|
|
1429
1444
|
...(langOf(deps, key) ? { lang: langOf(deps, key) } : {}),
|
|
1430
1445
|
};
|
|
@@ -1463,6 +1478,7 @@ const quoteForCard = (quote, groupOf) => ({
|
|
|
1463
1478
|
...(l.bedTypes ? { bedTypes: l.bedTypes } : {}),
|
|
1464
1479
|
...(l.window ? { window: l.window } : {}),
|
|
1465
1480
|
...(l.meal ? { meal: l.meal } : {}),
|
|
1481
|
+
...(l.rate ? { rate: l.rate } : {}),
|
|
1466
1482
|
stay: l.stay,
|
|
1467
1483
|
nights: l.nights,
|
|
1468
1484
|
...(l.hourly ? { hourly: l.hourly } : {}),
|
|
@@ -2067,7 +2083,11 @@ const currentTrip = async (deps, key, who) => {
|
|
|
2067
2083
|
...needs,
|
|
2068
2084
|
count: lines.length,
|
|
2069
2085
|
},
|
|
2070
|
-
text: [
|
|
2086
|
+
text: [
|
|
2087
|
+
tripText(only, false),
|
|
2088
|
+
orphans.line,
|
|
2089
|
+
deps.vocab.demo && lines.length ? noteFor(deps.vocab) : '',
|
|
2090
|
+
]
|
|
2071
2091
|
.filter(Boolean)
|
|
2072
2092
|
.join('\n'),
|
|
2073
2093
|
};
|
|
@@ -2108,7 +2128,7 @@ const currentTrip = async (deps, key, who) => {
|
|
|
2108
2128
|
`This trip is in ${parts.length} currencies, priced separately and not converted - each hotel is booked and paid in its own.`,
|
|
2109
2129
|
...parts.map((q) => tripText(q, false)),
|
|
2110
2130
|
orphans.line,
|
|
2111
|
-
deps.vocab.demo ?
|
|
2131
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
2112
2132
|
]
|
|
2113
2133
|
.filter(Boolean)
|
|
2114
2134
|
.join('\n\n'),
|
|
@@ -2921,7 +2941,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
2921
2941
|
: `**${h.name}** · ${offerCount(enough)} for ${stay.checkIn} to ${stay.checkOut}, ${stay.guests} guests${roomsWanted > 1 ? `, ${roomsWanted} rooms` : ''}.`,
|
|
2922
2942
|
...enough.map((r) => `- ${r.name}${labelWords(r)} — ${priceWords(r)}${roomsWanted > 1 ? ` (${formatMoney(multiplyMoney(r.stayTotal, roomsWanted))} for ${roomsWanted} rooms)` : ''}${r.freeCancellationUntil ? `, free to cancel until ${freeUntilText(r)}` : r.refundable ? ', the free cancellation window has closed - cancelling now has a fee' : ', non-refundable'}`),
|
|
2923
2943
|
flex.text,
|
|
2924
|
-
deps.vocab.demo ?
|
|
2944
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
2925
2945
|
]
|
|
2926
2946
|
.filter(Boolean)
|
|
2927
2947
|
.join('\n'),
|
|
@@ -3054,7 +3074,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3054
3074
|
// Only tools this deployment offers: a name it withholds is one the
|
|
3055
3075
|
// model would try (2026-10-05 audit, P2 - Huazhu has no add-ons).
|
|
3056
3076
|
[t.listHotels, t.getHotel, t.listExtras].filter((n) => !deps.offered || deps.offered.has(n)))} would each draw a card of their own.`,
|
|
3057
|
-
deps.vocab.demo ?
|
|
3077
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3058
3078
|
]
|
|
3059
3079
|
.filter(Boolean)
|
|
3060
3080
|
.join('\n\n'),
|
|
@@ -3138,7 +3158,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3138
3158
|
text: extras.length
|
|
3139
3159
|
? extras
|
|
3140
3160
|
.map((e) => `- ${e.name} — ${formatMoney(e.price)} ${unitWords(e.per)}${held[e.id] ? ` (${booked?.confirmationCode} holds ${held[e.id]})` : ''}`)
|
|
3141
|
-
.concat(deps.vocab.demo ? [
|
|
3161
|
+
.concat(deps.vocab.demo ? [noteFor(deps.vocab)] : [])
|
|
3142
3162
|
.join('\n')
|
|
3143
3163
|
: `${detail.hotel.name} has no add-ons listed here.`,
|
|
3144
3164
|
};
|
|
@@ -3579,7 +3599,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3579
3599
|
...failedText,
|
|
3580
3600
|
remembered?.line ?? '',
|
|
3581
3601
|
others ? `The trip's other stays are still in it, not booked:\n${rest?.text ?? ''}` : '',
|
|
3582
|
-
deps.vocab.demo ?
|
|
3602
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3583
3603
|
]
|
|
3584
3604
|
.filter(Boolean)
|
|
3585
3605
|
.join('\n'),
|
|
@@ -3723,7 +3743,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3723
3743
|
preview.rule,
|
|
3724
3744
|
`Say the word and it moves (${t.changeBooking} with \`confirmed\`).`,
|
|
3725
3745
|
demoBookingNote(deps, preview.supplier),
|
|
3726
|
-
deps.vocab.demo ?
|
|
3746
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3727
3747
|
]
|
|
3728
3748
|
.filter(Boolean)
|
|
3729
3749
|
.join(' ')
|
|
@@ -3786,7 +3806,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3786
3806
|
`${changed.confirmationCode} now holds ${changed.stay.checkIn} to ${changed.stay.checkOut}, ${formatMoney(changed.quote.total)} all in.`,
|
|
3787
3807
|
'The confirmation code has not changed. **Nothing has been charged.**',
|
|
3788
3808
|
demoBookingNote(deps, changed.supplier),
|
|
3789
|
-
deps.vocab.demo ?
|
|
3809
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3790
3810
|
]
|
|
3791
3811
|
.filter(Boolean)
|
|
3792
3812
|
.join(' '),
|
|
@@ -3834,7 +3854,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3834
3854
|
? `Say the word and it is cancelled (${t.cancelBooking} with \`confirmed\`).`
|
|
3835
3855
|
: '',
|
|
3836
3856
|
demoBookingNote(deps, preview.supplier),
|
|
3837
|
-
deps.vocab.demo ?
|
|
3857
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3838
3858
|
]
|
|
3839
3859
|
.filter(Boolean)
|
|
3840
3860
|
.join(' '),
|
|
@@ -3886,12 +3906,14 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3886
3906
|
: h.sandbox
|
|
3887
3907
|
? // A test booking cancelled in the simulation: no hotel, no charge (2026-10-05 audit, P2).
|
|
3888
3908
|
`${cancelled.confirmationCode} is cancelled in the simulated system. ${charged.minor === 0 ? 'No fee.' : `A real booking on this rate would be charged ${formatMoney(charged)}; this one is a test, and nothing is charged.`}`
|
|
3889
|
-
: h.
|
|
3890
|
-
?
|
|
3891
|
-
|
|
3892
|
-
|
|
3909
|
+
: h.test
|
|
3910
|
+
? `${cancelled.confirmationCode} is cancelled in ${h.name}'s test system. ${charged.minor === 0 ? 'No fee.' : `A live booking on this rate would be charged ${formatMoney(charged)}; this one is a test, and nothing is charged.`}`
|
|
3911
|
+
: h.demo
|
|
3912
|
+
? // Nobody charges a demonstration anything (2026-10-05 audit, P2).
|
|
3913
|
+
`${cancelled.confirmationCode} is cancelled. ${charged.minor === 0 ? 'No fee.' : `A real booking on this rate would be charged ${formatMoney(charged)}; this is a demonstration, and nothing is charged.`}`
|
|
3914
|
+
: `${cancelled.confirmationCode} is cancelled. ${charged.minor === 0 ? 'No fee.' : `The hotel charges ${formatMoney(charged)}.`}`,
|
|
3893
3915
|
demoBookingNote(deps, cancelled.supplier),
|
|
3894
|
-
deps.vocab.demo ?
|
|
3916
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3895
3917
|
]
|
|
3896
3918
|
.filter(Boolean)
|
|
3897
3919
|
.join(' '),
|
|
@@ -3955,7 +3977,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3955
3977
|
: '',
|
|
3956
3978
|
...comparison.dropped.map((d) => `Left out: ${d.name} — ${d.why}`),
|
|
3957
3979
|
...fitsManyOf(deps, comparison.dropped),
|
|
3958
|
-
deps.vocab.demo ?
|
|
3980
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3959
3981
|
]
|
|
3960
3982
|
.filter(Boolean)
|
|
3961
3983
|
.join('\n'),
|
|
@@ -3999,7 +4021,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3999
4021
|
stays.length ? `Stays, priced on: ${stays.join('; ')}.` : '',
|
|
4000
4022
|
...plan.dropped.map((d) => `Left out: ${d.name} — ${d.why}`),
|
|
4001
4023
|
...fitsManyOf(deps, plan.dropped),
|
|
4002
|
-
deps.vocab.demo ?
|
|
4024
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
4003
4025
|
]
|
|
4004
4026
|
.filter(Boolean)
|
|
4005
4027
|
.join('\n'),
|
|
@@ -4048,7 +4070,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
4048
4070
|
member.preferences?.length
|
|
4049
4071
|
? `Saved preferences on this membership: ${member.preferences.map((k) => REQUEST_WORDS[k]).join(', ')}. They are ticked on the booking form; mention them, and ask before booking with them.`
|
|
4050
4072
|
: '',
|
|
4051
|
-
deps.vocab.demo ?
|
|
4073
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
4052
4074
|
]
|
|
4053
4075
|
.filter(Boolean)
|
|
4054
4076
|
.join(' '),
|