@curless/hotel-storefront 0.34.0 → 0.35.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.
- 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 +13 -0
- 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 +38 -1
- package/dist/huazhu/backend.js.map +1 -1
- package/dist/legal.d.ts.map +1 -1
- package/dist/legal.js +118 -82
- package/dist/legal.js.map +1 -1
- package/dist/payments/checkout.d.ts +24 -1
- package/dist/payments/checkout.d.ts.map +1 -1
- package/dist/payments/checkout.js.map +1 -1
- package/dist/payments/fake-stripe.d.ts +34 -0
- package/dist/payments/fake-stripe.d.ts.map +1 -0
- package/dist/payments/fake-stripe.js +93 -0
- package/dist/payments/fake-stripe.js.map +1 -0
- package/dist/payments/stripe-checkout.d.ts +36 -0
- package/dist/payments/stripe-checkout.d.ts.map +1 -0
- package/dist/payments/stripe-checkout.js +126 -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 +42 -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 +13 -0
- package/dist/vocab.d.ts.map +1 -1
- package/dist/vocab.js +22 -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,8 @@ 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
|
+
...(deps.vocab.test ? { test: true } : {}),
|
|
1416
1428
|
...(caps.programme ? { programme: caps.programme } : {}),
|
|
1417
1429
|
...(caps.codePrefix ? { codePrefix: caps.codePrefix } : {}),
|
|
1418
1430
|
// Sells rooms by the hour: the card draws its Overnight / By the hour
|
|
@@ -1424,7 +1436,7 @@ const common = (deps, key) => {
|
|
|
1424
1436
|
? { market: { name: deps.vocab.brand, suppliers: deps.backend.suppliers() } }
|
|
1425
1437
|
: {}),
|
|
1426
1438
|
vocab: { noun: deps.vocab.noun, nounPlural: deps.vocab.nounPlural },
|
|
1427
|
-
...(deps.vocab.demo ? { demo: true, demoNote:
|
|
1439
|
+
...(deps.vocab.demo ? { demo: true, demoNote: noteFor(deps.vocab) } : { demo: false }),
|
|
1428
1440
|
...(key ? memberBadge(deps, key) : {}),
|
|
1429
1441
|
...(langOf(deps, key) ? { lang: langOf(deps, key) } : {}),
|
|
1430
1442
|
};
|
|
@@ -1463,6 +1475,7 @@ const quoteForCard = (quote, groupOf) => ({
|
|
|
1463
1475
|
...(l.bedTypes ? { bedTypes: l.bedTypes } : {}),
|
|
1464
1476
|
...(l.window ? { window: l.window } : {}),
|
|
1465
1477
|
...(l.meal ? { meal: l.meal } : {}),
|
|
1478
|
+
...(l.rate ? { rate: l.rate } : {}),
|
|
1466
1479
|
stay: l.stay,
|
|
1467
1480
|
nights: l.nights,
|
|
1468
1481
|
...(l.hourly ? { hourly: l.hourly } : {}),
|
|
@@ -2067,7 +2080,11 @@ const currentTrip = async (deps, key, who) => {
|
|
|
2067
2080
|
...needs,
|
|
2068
2081
|
count: lines.length,
|
|
2069
2082
|
},
|
|
2070
|
-
text: [
|
|
2083
|
+
text: [
|
|
2084
|
+
tripText(only, false),
|
|
2085
|
+
orphans.line,
|
|
2086
|
+
deps.vocab.demo && lines.length ? noteFor(deps.vocab) : '',
|
|
2087
|
+
]
|
|
2071
2088
|
.filter(Boolean)
|
|
2072
2089
|
.join('\n'),
|
|
2073
2090
|
};
|
|
@@ -2108,7 +2125,7 @@ const currentTrip = async (deps, key, who) => {
|
|
|
2108
2125
|
`This trip is in ${parts.length} currencies, priced separately and not converted - each hotel is booked and paid in its own.`,
|
|
2109
2126
|
...parts.map((q) => tripText(q, false)),
|
|
2110
2127
|
orphans.line,
|
|
2111
|
-
deps.vocab.demo ?
|
|
2128
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
2112
2129
|
]
|
|
2113
2130
|
.filter(Boolean)
|
|
2114
2131
|
.join('\n\n'),
|
|
@@ -2921,7 +2938,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
2921
2938
|
: `**${h.name}** · ${offerCount(enough)} for ${stay.checkIn} to ${stay.checkOut}, ${stay.guests} guests${roomsWanted > 1 ? `, ${roomsWanted} rooms` : ''}.`,
|
|
2922
2939
|
...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
2940
|
flex.text,
|
|
2924
|
-
deps.vocab.demo ?
|
|
2941
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
2925
2942
|
]
|
|
2926
2943
|
.filter(Boolean)
|
|
2927
2944
|
.join('\n'),
|
|
@@ -3054,7 +3071,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3054
3071
|
// Only tools this deployment offers: a name it withholds is one the
|
|
3055
3072
|
// model would try (2026-10-05 audit, P2 - Huazhu has no add-ons).
|
|
3056
3073
|
[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 ?
|
|
3074
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3058
3075
|
]
|
|
3059
3076
|
.filter(Boolean)
|
|
3060
3077
|
.join('\n\n'),
|
|
@@ -3138,7 +3155,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3138
3155
|
text: extras.length
|
|
3139
3156
|
? extras
|
|
3140
3157
|
.map((e) => `- ${e.name} — ${formatMoney(e.price)} ${unitWords(e.per)}${held[e.id] ? ` (${booked?.confirmationCode} holds ${held[e.id]})` : ''}`)
|
|
3141
|
-
.concat(deps.vocab.demo ? [
|
|
3158
|
+
.concat(deps.vocab.demo ? [noteFor(deps.vocab)] : [])
|
|
3142
3159
|
.join('\n')
|
|
3143
3160
|
: `${detail.hotel.name} has no add-ons listed here.`,
|
|
3144
3161
|
};
|
|
@@ -3579,7 +3596,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3579
3596
|
...failedText,
|
|
3580
3597
|
remembered?.line ?? '',
|
|
3581
3598
|
others ? `The trip's other stays are still in it, not booked:\n${rest?.text ?? ''}` : '',
|
|
3582
|
-
deps.vocab.demo ?
|
|
3599
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3583
3600
|
]
|
|
3584
3601
|
.filter(Boolean)
|
|
3585
3602
|
.join('\n'),
|
|
@@ -3723,7 +3740,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3723
3740
|
preview.rule,
|
|
3724
3741
|
`Say the word and it moves (${t.changeBooking} with \`confirmed\`).`,
|
|
3725
3742
|
demoBookingNote(deps, preview.supplier),
|
|
3726
|
-
deps.vocab.demo ?
|
|
3743
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3727
3744
|
]
|
|
3728
3745
|
.filter(Boolean)
|
|
3729
3746
|
.join(' ')
|
|
@@ -3786,7 +3803,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3786
3803
|
`${changed.confirmationCode} now holds ${changed.stay.checkIn} to ${changed.stay.checkOut}, ${formatMoney(changed.quote.total)} all in.`,
|
|
3787
3804
|
'The confirmation code has not changed. **Nothing has been charged.**',
|
|
3788
3805
|
demoBookingNote(deps, changed.supplier),
|
|
3789
|
-
deps.vocab.demo ?
|
|
3806
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3790
3807
|
]
|
|
3791
3808
|
.filter(Boolean)
|
|
3792
3809
|
.join(' '),
|
|
@@ -3834,7 +3851,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3834
3851
|
? `Say the word and it is cancelled (${t.cancelBooking} with \`confirmed\`).`
|
|
3835
3852
|
: '',
|
|
3836
3853
|
demoBookingNote(deps, preview.supplier),
|
|
3837
|
-
deps.vocab.demo ?
|
|
3854
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3838
3855
|
]
|
|
3839
3856
|
.filter(Boolean)
|
|
3840
3857
|
.join(' '),
|
|
@@ -3886,12 +3903,14 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3886
3903
|
: h.sandbox
|
|
3887
3904
|
? // A test booking cancelled in the simulation: no hotel, no charge (2026-10-05 audit, P2).
|
|
3888
3905
|
`${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
|
-
|
|
3906
|
+
: h.test
|
|
3907
|
+
? `${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.`}`
|
|
3908
|
+
: h.demo
|
|
3909
|
+
? // Nobody charges a demonstration anything (2026-10-05 audit, P2).
|
|
3910
|
+
`${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.`}`
|
|
3911
|
+
: `${cancelled.confirmationCode} is cancelled. ${charged.minor === 0 ? 'No fee.' : `The hotel charges ${formatMoney(charged)}.`}`,
|
|
3893
3912
|
demoBookingNote(deps, cancelled.supplier),
|
|
3894
|
-
deps.vocab.demo ?
|
|
3913
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3895
3914
|
]
|
|
3896
3915
|
.filter(Boolean)
|
|
3897
3916
|
.join(' '),
|
|
@@ -3955,7 +3974,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3955
3974
|
: '',
|
|
3956
3975
|
...comparison.dropped.map((d) => `Left out: ${d.name} — ${d.why}`),
|
|
3957
3976
|
...fitsManyOf(deps, comparison.dropped),
|
|
3958
|
-
deps.vocab.demo ?
|
|
3977
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
3959
3978
|
]
|
|
3960
3979
|
.filter(Boolean)
|
|
3961
3980
|
.join('\n'),
|
|
@@ -3999,7 +4018,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
3999
4018
|
stays.length ? `Stays, priced on: ${stays.join('; ')}.` : '',
|
|
4000
4019
|
...plan.dropped.map((d) => `Left out: ${d.name} — ${d.why}`),
|
|
4001
4020
|
...fitsManyOf(deps, plan.dropped),
|
|
4002
|
-
deps.vocab.demo ?
|
|
4021
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
4003
4022
|
]
|
|
4004
4023
|
.filter(Boolean)
|
|
4005
4024
|
.join('\n'),
|
|
@@ -4048,7 +4067,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
4048
4067
|
member.preferences?.length
|
|
4049
4068
|
? `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
4069
|
: '',
|
|
4051
|
-
deps.vocab.demo ?
|
|
4070
|
+
deps.vocab.demo ? noteFor(deps.vocab) : '',
|
|
4052
4071
|
]
|
|
4053
4072
|
.filter(Boolean)
|
|
4054
4073
|
.join(' '),
|