@agenzo/merchant-cli 0.9.2 → 0.9.4
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 +343 -343
- package/dist/index.js +50 -5
- package/dist/index.js.map +1 -1
- package/package.json +28 -28
package/dist/index.js
CHANGED
|
@@ -62,6 +62,7 @@ var CODE_NUM = {
|
|
|
62
62
|
BOOKING_RESTRICTED: 4310,
|
|
63
63
|
PAYORDER_FAILED: 4311,
|
|
64
64
|
PAYORDER_FAILED_AFTER_PAYMENT: 4312,
|
|
65
|
+
OFFER_UNAVAILABLE: 4401,
|
|
65
66
|
RATE_LIMITED: 5001,
|
|
66
67
|
UPSTREAM_ERROR: 5101,
|
|
67
68
|
INTERNAL_ERROR: 5201,
|
|
@@ -249,6 +250,7 @@ var STABLE_MESSAGE = {
|
|
|
249
250
|
BOOKING_RESTRICTED: "This room has a booking condition that your request doesn't meet. Please check the room's booking rules and adjust your request.",
|
|
250
251
|
PAYORDER_FAILED: "The hotel order was created, but payment failed. Retry payment for the existing order.",
|
|
251
252
|
PAYORDER_FAILED_AFTER_PAYMENT: "Payment was received, but hotel confirmation failed. Contact support for reconciliation.",
|
|
253
|
+
OFFER_UNAVAILABLE: "The selected flight is no longer available. Please search again and pick another flight.",
|
|
252
254
|
NOT_IMPLEMENTED: "This operation is not implemented yet."
|
|
253
255
|
};
|
|
254
256
|
function errorDetailLines(envelope) {
|
|
@@ -329,6 +331,8 @@ function isBelow(current, minimum) {
|
|
|
329
331
|
return compareVersions(current, minimum) < 0;
|
|
330
332
|
}
|
|
331
333
|
var TRACEPARENT_PATTERN = /^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$/;
|
|
334
|
+
var FLOW_ID_BAGGAGE_KEY = "agenzo.flow_id";
|
|
335
|
+
var FLOW_ID_PATTERN = /^flw_[A-Za-z0-9_-]{8,60}$/;
|
|
332
336
|
var DEFAULT_HTTP_TIMEOUT_MS = 7e4;
|
|
333
337
|
function httpTimeoutFromEnv(env = process.env) {
|
|
334
338
|
const raw = env.AGENZO_CLI_HTTP_TIMEOUT_MS;
|
|
@@ -338,6 +342,25 @@ function httpTimeoutFromEnv(env = process.env) {
|
|
|
338
342
|
return parsed;
|
|
339
343
|
}
|
|
340
344
|
var DEADLINE_HEADER = "x-deadline-ms";
|
|
345
|
+
var BAGGAGE_HEADER = "baggage";
|
|
346
|
+
function baggageFromEnv(env = process.env) {
|
|
347
|
+
const raw = env.BAGGAGE;
|
|
348
|
+
if (raw === void 0 || raw.trim() === "") return null;
|
|
349
|
+
for (const member of raw.split(",")) {
|
|
350
|
+
const pair = member.split(";", 1)[0] ?? "";
|
|
351
|
+
const eq = pair.indexOf("=");
|
|
352
|
+
if (eq < 0) continue;
|
|
353
|
+
if (pair.slice(0, eq).trim() !== FLOW_ID_BAGGAGE_KEY) continue;
|
|
354
|
+
let value = pair.slice(eq + 1).trim();
|
|
355
|
+
try {
|
|
356
|
+
value = decodeURIComponent(value);
|
|
357
|
+
} catch {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
return FLOW_ID_PATTERN.test(value) ? `${FLOW_ID_BAGGAGE_KEY}=${encodeURIComponent(value)}` : null;
|
|
361
|
+
}
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
341
364
|
var DEADLINE_RESERVE_MS = 200;
|
|
342
365
|
function deadlineFromEnv(env = process.env) {
|
|
343
366
|
const raw = env.DEADLINE_MS;
|
|
@@ -399,6 +422,10 @@ var ApiClient = class {
|
|
|
399
422
|
if (traceparent && TRACEPARENT_PATTERN.test(traceparent.trim())) {
|
|
400
423
|
headers["traceparent"] = traceparent.trim();
|
|
401
424
|
}
|
|
425
|
+
const baggage = baggageFromEnv();
|
|
426
|
+
if (baggage !== null) {
|
|
427
|
+
headers[BAGGAGE_HEADER] = baggage;
|
|
428
|
+
}
|
|
402
429
|
if (auth.type === "bearer") {
|
|
403
430
|
headers["Authorization"] = `Bearer ${auth.token}`;
|
|
404
431
|
} else if (auth.type === "api-key") {
|
|
@@ -2432,13 +2459,21 @@ var flightMoreOffersSchema = flightSchema(
|
|
|
2432
2459
|
);
|
|
2433
2460
|
var flightVerifySchema = flightSchema(
|
|
2434
2461
|
"verify",
|
|
2435
|
-
"Pre-booking price verification. Returns the authoritative product_token and a price_changed flag; pass the returned token to create-order.",
|
|
2436
|
-
{
|
|
2462
|
+
"Pre-booking price verification. Returns the authoritative product_token and a price_changed flag; pass the returned token to create-order. With --previous-total-price set, supplier 1002/1950 no longer dead-ends: the platform re-searches the SAME flight from the token and returns the refreshed fare; if that flight can no longer be found it fails with OFFER_UNAVAILABLE (pick another flight).",
|
|
2463
|
+
{
|
|
2464
|
+
"product-token": { type: "string", required: true, description: "Opaque token from search." },
|
|
2465
|
+
"previous-total-price": { type: "int", required: false, description: "Total price of the selected offer; enables the one-shot re-search refresh on supplier 1002/1950. Omit to keep the legacy behavior (error surfaces as-is)." },
|
|
2466
|
+
"cabin-class": { type: "string", required: false, description: "Cabin class to re-search with when refreshing (economy | premium_economy | business | first). Omitted falls back to economy." },
|
|
2467
|
+
"adult-num": { type: "int", required: false, description: "Adults to re-search with when refreshing (1-9)." },
|
|
2468
|
+
"child-num": { type: "int", required: false, description: "Children to re-search with when refreshing (0-9)." },
|
|
2469
|
+
"infant-num": { type: "int", required: false, description: "Infants to re-search with when refreshing (0-9)." }
|
|
2470
|
+
},
|
|
2437
2471
|
{
|
|
2438
2472
|
product_token: { type: "string", description: "Authoritative token to pass to create-order." },
|
|
2439
2473
|
total_price: { type: "int", description: "Verified total price (integer)." },
|
|
2440
2474
|
currency: { type: "string", description: "Currency code." },
|
|
2441
2475
|
price_changed: { type: "bool", description: "True if the price changed since search; re-confirm with the user." },
|
|
2476
|
+
previous_total_price: { type: "int", description: "The selected offer\u2019s price at pick time; present when the request carried previous-total-price. If it differs from total_price the fare was refreshed by a re-search (show the user the old \u2192 new price)." },
|
|
2442
2477
|
journeys: { type: "array", description: "The COMPLETE itinerary being priced \u2014 every leg, not just the last one relayed. Use it to show the full trip on a confirmation screen." }
|
|
2443
2478
|
},
|
|
2444
2479
|
{ command: "agenzo-merchant-cli flight-flink verify --product-token pt_...", output_summary: "Returns the authoritative product_token + price_changed." }
|
|
@@ -6325,18 +6360,26 @@ function registerMoreOffersCommand(parent, deps) {
|
|
|
6325
6360
|
|
|
6326
6361
|
// src/flight-flink/verify.ts
|
|
6327
6362
|
function registerVerifyCommand(parent, deps) {
|
|
6328
|
-
const cmd = parent.command("verify").description("Verify the latest price before booking; returns the authoritative product_token").option("--api-key <key>", "API Key for authentication (X-Api-Key)").option("--product-token <token>", "Opaque token from search");
|
|
6363
|
+
const cmd = parent.command("verify").description("Verify the latest price before booking; returns the authoritative product_token").option("--api-key <key>", "API Key for authentication (X-Api-Key)").option("--product-token <token>", "Opaque token from search").option("--previous-total-price <n>", "Total price of the selected offer; enables the one-shot re-search refresh on supplier 1002/1950").option("--cabin-class <c>", "Cabin class to re-search with (economy | premium_economy | business | first)").option("--adult-num <n>", "Adults to re-search with (1-9)").option("--child-num <n>", "Children to re-search with (0-9)").option("--infant-num <n>", "Infants to re-search with (0-9)");
|
|
6329
6364
|
attachSchemaHelp(cmd, flightVerifySchema);
|
|
6330
6365
|
cmd.action(async () => {
|
|
6331
6366
|
const opts = cmd.optsWithGlobals();
|
|
6332
6367
|
const format = resolveFormat(opts.format);
|
|
6333
6368
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6334
6369
|
const productToken = need21(opts.productToken, "product-token");
|
|
6370
|
+
const body = { product_token: productToken };
|
|
6371
|
+
if (opts.previousTotalPrice !== void 0) {
|
|
6372
|
+
body.previous_total_price = num10(opts.previousTotalPrice, "previous-total-price");
|
|
6373
|
+
}
|
|
6374
|
+
if (opts.cabinClass !== void 0) body.cabin_class = opts.cabinClass;
|
|
6375
|
+
if (opts.adultNum !== void 0) body.adult_num = num10(opts.adultNum, "adult-num");
|
|
6376
|
+
if (opts.childNum !== void 0) body.child_num = num10(opts.childNum, "child-num");
|
|
6377
|
+
if (opts.infantNum !== void 0) body.infant_num = num10(opts.infantNum, "infant-num");
|
|
6335
6378
|
const spinner = format === "json" ? null : createSpinner("Verifying price...");
|
|
6336
6379
|
const result = await deps.apiClient.post(
|
|
6337
6380
|
"/flight/verify",
|
|
6338
6381
|
{ type: "api-key", key: apiKey },
|
|
6339
|
-
|
|
6382
|
+
body
|
|
6340
6383
|
);
|
|
6341
6384
|
spinner?.stop();
|
|
6342
6385
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
@@ -6346,7 +6389,9 @@ function registerVerifyCommand(parent, deps) {
|
|
|
6346
6389
|
(d) => Formatter.keyValue([
|
|
6347
6390
|
["Product token", String(d.product_token ?? "-")],
|
|
6348
6391
|
["Total price", `${d.total_price ?? "-"} ${d.currency ?? ""}`.trim()],
|
|
6349
|
-
["Price changed", String(d.price_changed)]
|
|
6392
|
+
["Price changed", String(d.price_changed)],
|
|
6393
|
+
// 刷新路径:平台带回选中时的原价,人读 output 里直接看出 原价 → 新价。
|
|
6394
|
+
...d.previous_total_price != null ? [["Previous total price", String(d.previous_total_price)]] : []
|
|
6350
6395
|
])
|
|
6351
6396
|
);
|
|
6352
6397
|
});
|